diff --git a/cmd/lemming/BUILD b/cmd/lemming/BUILD index fb19628b..e23e475c 100644 --- a/cmd/lemming/BUILD +++ b/cmd/lemming/BUILD @@ -9,6 +9,8 @@ go_library( visibility = ["//visibility:private"], deps = [ "//:lemming", + "//dataplane/config", + "//proto/forwarding", "//sysrib", "@com_github_golang_glog//:glog", "@com_github_spf13_pflag//:pflag", diff --git a/cmd/lemming/lemming.go b/cmd/lemming/lemming.go index c799aff9..123f65e4 100644 --- a/cmd/lemming/lemming.go +++ b/cmd/lemming/lemming.go @@ -23,9 +23,12 @@ import ( "google.golang.org/grpc/credentials/insecure" "github.com/openconfig/lemming" + "github.com/openconfig/lemming/dataplane/config" "github.com/openconfig/lemming/sysrib" log "github.com/golang/glog" + + fwdpb "github.com/openconfig/lemming/proto/forwarding" ) var ( @@ -43,6 +46,8 @@ func main() { pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() viper.BindPFlags(pflag.CommandLine) + // TODO: A better way to config, this doesn't need to a be a flag. + viper.Set(config.NetDevForwardingType, fwdpb.PortType_name[int32(fwdpb.PortType_PORT_TYPE_TAP)]) creds := insecure.NewCredentials() if *tlsCertFile != "" && *tlsKeyFile != "" { diff --git a/dataplane/BUILD b/dataplane/BUILD index fce55910..c643fb4a 100644 --- a/dataplane/BUILD +++ b/dataplane/BUILD @@ -10,57 +10,57 @@ go_library( importpath = "github.com/openconfig/lemming/dataplane", visibility = ["//visibility:public"], deps = [ - "//dataplane/internal/engine", + "//dataplane/standalone/proto:sai", + "//dataplane/standalone/saiserver", + "//dataplane/standalone/saiserver/attrmgr", "//gnmi/oc", "//gnmi/reconciler", - "//proto/dataplane", - "//proto/forwarding", "@com_github_openconfig_gnmi//proto/gnmi", "@com_github_openconfig_ygnmi//ygnmi", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//credentials/local", ] + select({ "@io_bazel_rules_go//go/platform:aix": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:android": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:darwin": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:dragonfly": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:freebsd": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:illumos": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:ios": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:js": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:linux": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:netbsd": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:openbsd": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:plan9": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:solaris": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "@io_bazel_rules_go//go/platform:windows": [ - "//dataplane/handlers", + "//dataplane/dplanerc", ], "//conditions:default": [], }), diff --git a/dataplane/config/BUILD b/dataplane/config/BUILD new file mode 100644 index 00000000..92e2d0c3 --- /dev/null +++ b/dataplane/config/BUILD @@ -0,0 +1,12 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "config", + srcs = ["config.go"], + importpath = "github.com/openconfig/lemming/dataplane/config", + visibility = ["//visibility:public"], + deps = [ + "//proto/forwarding", + "@com_github_spf13_viper//:viper", + ], +) diff --git a/dataplane/config/config.go b/dataplane/config/config.go new file mode 100644 index 00000000..f48fc498 --- /dev/null +++ b/dataplane/config/config.go @@ -0,0 +1,30 @@ +// Copyright 2022 Google LLC +// +// 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 config + +import ( + "github.com/spf13/viper" + + fwdpb "github.com/openconfig/lemming/proto/forwarding" +) + +const ( + // NetDevForwardingType configures the forwarding type of a SAI netdev hostif. Options are (KERNEL and TAP). + NetDevForwardingType = "dataplane.netDevType" +) + +func init() { + viper.Set(NetDevForwardingType, fwdpb.PortType_name[int32(fwdpb.PortType_PORT_TYPE_KERNEL)]) +} diff --git a/dataplane/handlers/BUILD b/dataplane/dplanerc/BUILD similarity index 64% rename from dataplane/handlers/BUILD rename to dataplane/dplanerc/BUILD index f0b9e305..eed22cdd 100644 --- a/dataplane/handlers/BUILD +++ b/dataplane/dplanerc/BUILD @@ -1,40 +1,48 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( - name = "handlers", + name = "dplanerc", srcs = [ "interface.go", "routes.go", ], - importpath = "github.com/openconfig/lemming/dataplane/handlers", + importpath = "github.com/openconfig/lemming/dataplane/dplanerc", visibility = ["//visibility:public"], deps = [ "//dataplane/internal/engine", + "//dataplane/standalone/proto:sai", "//gnmi", - "//gnmi/reconciler", "//proto/dataplane", + "//proto/forwarding", "@com_github_golang_glog//:glog", + "@com_github_google_gopacket//:gopacket", + "@com_github_google_gopacket//layers", "@com_github_openconfig_ygnmi//schemaless", "@com_github_openconfig_ygnmi//ygnmi", + "@org_golang_google_protobuf//proto", ] + select({ "@io_bazel_rules_go//go/platform:android": [ + "//dataplane/forwarding/fwdconfig", "//dataplane/internal/kernel", + "//dataplane/standalone/packetio/cpusink", "//gnmi/gnmiclient", "//gnmi/oc", "//gnmi/oc/ocpath", - "//proto/forwarding", "@com_github_openconfig_ygot//ygot", "@com_github_vishvananda_netlink//:netlink", + "@org_golang_google_grpc//:go_default_library", "@org_golang_x_sys//unix", ], "@io_bazel_rules_go//go/platform:linux": [ + "//dataplane/forwarding/fwdconfig", "//dataplane/internal/kernel", + "//dataplane/standalone/packetio/cpusink", "//gnmi/gnmiclient", "//gnmi/oc", "//gnmi/oc/ocpath", - "//proto/forwarding", "@com_github_openconfig_ygot//ygot", "@com_github_vishvananda_netlink//:netlink", + "@org_golang_google_grpc//:go_default_library", "@org_golang_x_sys//unix", ], "//conditions:default": [], diff --git a/dataplane/dplanerc/interface.go b/dataplane/dplanerc/interface.go new file mode 100644 index 00000000..f9e75f91 --- /dev/null +++ b/dataplane/dplanerc/interface.go @@ -0,0 +1,748 @@ +// Copyright 2022 Google LLC +// +// 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. + +//go:build linux + +// Package dplanerc contains gNMI task handlers. +package dplanerc + +import ( + "context" + "fmt" + "net" + "strings" + "sync" + "time" + + "github.com/openconfig/ygnmi/ygnmi" + "github.com/openconfig/ygot/ygot" + "github.com/vishvananda/netlink" + "golang.org/x/sys/unix" + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" + + "github.com/openconfig/lemming/dataplane/forwarding/fwdconfig" + "github.com/openconfig/lemming/dataplane/internal/kernel" + "github.com/openconfig/lemming/dataplane/standalone/packetio/cpusink" + "github.com/openconfig/lemming/gnmi/gnmiclient" + "github.com/openconfig/lemming/gnmi/oc" + "github.com/openconfig/lemming/gnmi/oc/ocpath" + + log "github.com/golang/glog" + + saipb "github.com/openconfig/lemming/dataplane/standalone/proto" + fwdpb "github.com/openconfig/lemming/proto/forwarding" +) + +type ocInterface struct { + name string + subintf uint32 +} + +type interfaceData struct { + portID uint64 + hostifID uint64 + hostifIfIndex int + hostifDevName string + rifID uint64 +} + +type interfaceMap map[ocInterface]*interfaceData + +func (d interfaceMap) findByIfIndex(ifIndex int) (ocInterface, *interfaceData) { + for k, v := range d { + if v.hostifIfIndex == ifIndex { + return k, v + } + } + return ocInterface{}, nil +} + +func (d interfaceMap) findByPortID(portID uint64) (ocInterface, *interfaceData) { + for k, v := range d { + if v.portID == portID { + return k, v + } + } + return ocInterface{}, nil +} + +// Reconciler handles config updates to the paths. +type Reconciler struct { + c *ygnmi.Client + // closers functions should all be invoked when the interface handler stops running. + closers []func() + hostifClient saipb.HostifClient + portClient saipb.PortClient + switchClient saipb.SwitchClient + ifaceClient saipb.RouterInterfaceClient + neighborClient saipb.NeighborClient + routeClient saipb.RouteClient + nextHopClient saipb.NextHopClient + fwdClient fwdpb.ForwardingClient + nextHopGroupClient saipb.NextHopGroupClient + stateMu sync.RWMutex + // state keeps track of the applied state of the device's interfaces so that we do not issue duplicate configuration commands to the device's interfaces. + state map[string]*oc.Interface + switchID uint64 + ifaceMgr interfaceManager + ocInterfaceData interfaceMap + cpuPortID uint64 + contextID string +} + +type interfaceManager interface { + SetHWAddr(name string, addr string) error + SetState(name string, up bool) error + ReplaceIP(name string, ip string, prefixLen int) error + DeleteIP(name string, ip string, prefixLen int) error + GetAll() ([]net.Interface, error) + GetByName(name string) (*net.Interface, error) + CreateTAP(name string) (int, error) + LinkSubscribe(ch chan<- netlink.LinkUpdate, done <-chan struct{}) error + AddrSubscribe(ch chan<- netlink.AddrUpdate, done <-chan struct{}) error + NeighSubscribe(ch chan<- netlink.NeighUpdate, done <-chan struct{}) error +} + +// New creates a new interface handler. +func New(conn grpc.ClientConnInterface, switchID, cpuPortID uint64, contextID string) *Reconciler { + r := &Reconciler{ + state: map[string]*oc.Interface{}, + ifaceMgr: &kernel.Interfaces{}, + switchID: switchID, + cpuPortID: cpuPortID, + contextID: contextID, + ocInterfaceData: interfaceMap{}, + hostifClient: saipb.NewHostifClient(conn), + portClient: saipb.NewPortClient(conn), + switchClient: saipb.NewSwitchClient(conn), + ifaceClient: saipb.NewRouterInterfaceClient(conn), + neighborClient: saipb.NewNeighborClient(conn), + routeClient: saipb.NewRouteClient(conn), + nextHopClient: saipb.NewNextHopClient(conn), + nextHopGroupClient: saipb.NewNextHopGroupClient(conn), + fwdClient: fwdpb.NewForwardingClient(conn), + } + return r +} + +// Start starts running the handler, watching the cache and the kernel interfaces. +func (ni *Reconciler) StartInterface(ctx context.Context, client *ygnmi.Client) error { + log.Info("starting interface handler") + b := &ocpath.Batch{} + ni.c = client + + if err := ni.setupPorts(ctx); err != nil { + return fmt.Errorf("failed to setup ports: %v", err) + } + + b.AddPaths( + ocpath.Root().InterfaceAny().Name().Config().PathStruct(), + ocpath.Root().InterfaceAny().Ethernet().MacAddress().Config().PathStruct(), + ocpath.Root().InterfaceAny().Subinterface(0).Enabled().Config().PathStruct(), // TODO: Support the parent interface config/enabled controling the subinterface state. + ocpath.Root().InterfaceAny().Subinterface(0).Ipv4().AddressAny().Ip().Config().PathStruct(), + ocpath.Root().InterfaceAny().Subinterface(0).Ipv4().AddressAny().PrefixLength().Config().PathStruct(), + ocpath.Root().InterfaceAny().Subinterface(0).Ipv6().AddressAny().Ip().Config().PathStruct(), + ocpath.Root().InterfaceAny().Subinterface(0).Ipv6().AddressAny().PrefixLength().Config().PathStruct(), + ) + cancelCtx, cancelFn := context.WithCancel(ctx) + + watcher := ygnmi.Watch(cancelCtx, ni.c, b.Config(), func(val *ygnmi.Value[*oc.Root]) error { + log.V(2).Info("reconciling interfaces") + root, ok := val.Val() + if !ok || root.Interface == nil { + return ygnmi.Continue + } + for _, i := range root.Interface { + ni.reconcile(cancelCtx, i) + } + return ygnmi.Continue + }) + + linkDoneCh := make(chan struct{}) + linkUpdateCh := make(chan netlink.LinkUpdate) + addrDoneCh := make(chan struct{}) + addrUpdateCh := make(chan netlink.AddrUpdate) + neighDoneCh := make(chan struct{}) + neighUpdateCh := make(chan netlink.NeighUpdate) + ni.closers = append(ni.closers, func() { + close(linkDoneCh) + close(addrDoneCh) + close(neighDoneCh) + }, cancelFn) + + if err := ni.ifaceMgr.LinkSubscribe(linkUpdateCh, linkDoneCh); err != nil { + return fmt.Errorf("failed to sub to link: %v", err) + } + if err := ni.ifaceMgr.AddrSubscribe(addrUpdateCh, addrDoneCh); err != nil { + return fmt.Errorf("failed to sub to addr: %v", err) + } + if err := ni.ifaceMgr.NeighSubscribe(neighUpdateCh, addrDoneCh); err != nil { + return fmt.Errorf("failed to sub to neighbor: %v", err) + } + notifClient, err := ni.switchClient.PortStateChangeNotification(cancelCtx, &saipb.PortStateChangeNotificationRequest{}) + if err != nil { + return err + } + go func() { + for { + n, err := notifClient.Recv() + if err != nil { + return + } + ni.handleDataplaneEvent(ctx, n) + } + }() + + go func() { + for { + select { + case up := <-linkUpdateCh: + ni.handleLinkUpdate(ctx, &up) + case up := <-addrUpdateCh: + ni.handleAddrUpdate(ctx, &up) + case up := <-neighUpdateCh: + ni.handleNeighborUpdate(ctx, &up) + } + } + }() + + go func() { + // TODO: handle error + if _, err := watcher.Await(); err != nil { + log.Warningf("interface watch err: %v", err) + } + }() + + ni.startCounterUpdates(ctx) + + return nil +} + +// Stop stops all watchers. +func (ni *Reconciler) Stop(context.Context) error { + // TODO: prevent stopping more than once. + for _, closeFn := range ni.closers { + closeFn() + } + return nil +} + +// startCounterUpdates starts a goroutine for updating counters for configured +// interfaces. +func (ni *Reconciler) startCounterUpdates(ctx context.Context) { + tick := time.NewTicker(time.Second) + ni.closers = append(ni.closers, tick.Stop) + go func() { + // Design comment: + // This polling can be eliminated if either the forwarding + // service supported streaming the counters, or if somehow the + // gnmi cache were able to forward queries to prompt the data + // producer to populate the leaf. + // + // However, given counters are likely frequently-updated values + // anyways, it may be fine for counter values to be polled. + for range tick.C { + ni.stateMu.RLock() + var intfNames []ocInterface + for intfName := range ni.state { + // TODO(wenbli): Support interface state deletion when interface is deleted. + intfNames = append(intfNames, ocInterface{name: intfName}) + } + ni.stateMu.RUnlock() + for _, intfName := range intfNames { + stats, err := ni.portClient.GetPortStats(ctx, &saipb.GetPortStatsRequest{ + Oid: ni.ocInterfaceData[intfName].portID, + CounterIds: []saipb.PortStat{ + saipb.PortStat_PORT_STAT_IF_IN_UCAST_PKTS, + saipb.PortStat_PORT_STAT_IF_IN_NON_UCAST_PKTS, + saipb.PortStat_PORT_STAT_IF_OUT_UCAST_PKTS, + saipb.PortStat_PORT_STAT_IF_OUT_NON_UCAST_PKTS, + }, + }) + log.V(2).Infof("querying counters for interface %q, got %v", intfName, stats) + if err != nil { + log.Errorf("interface handler: could not retrieve counter for interface %q", intfName) + continue + } + if _, err := gnmiclient.Replace(ctx, ni.c, ocpath.Root().Interface(intfName.name).Counters().InPkts().State(), stats.Values[0]+stats.Values[1]); err != nil { + log.Errorf("interface handler: %v", err) + } + if _, err := gnmiclient.Replace(ctx, ni.c, ocpath.Root().Interface(intfName.name).Counters().OutPkts().State(), stats.Values[2]+stats.Values[2]); err != nil { + log.Errorf("interface handler: %v", err) + } + } + } + }() +} + +// reconcile compares the interface config with state and modifies state to match config. +func (ni *Reconciler) reconcile(ctx context.Context, config *oc.Interface) { + ni.stateMu.RLock() + defer ni.stateMu.RUnlock() + + intf := ocInterface{name: config.GetName(), subintf: 0} + data := ni.ocInterfaceData[intf] + if data == nil { + return + } + state := ni.getOrCreateInterface(config.GetName()) + + if config.GetOrCreateEthernet().MacAddress != nil { + if config.GetEthernet().GetMacAddress() != state.GetEthernet().GetMacAddress() { + log.V(1).Infof("setting interface %s hw-addr %q", data.hostifDevName, config.GetEthernet().GetMacAddress()) + if err := ni.ifaceMgr.SetHWAddr(config.GetName(), config.GetEthernet().GetMacAddress()); err != nil { + log.Warningf("Failed to set mac address of port: %v", err) + } + } + } else { + // Deleting the configured MAC address means it should be the system-assigned MAC address, as detailed in the OpenConfig schema. + // https://openconfig.net/projects/models/schemadocs/yangdoc/openconfig-interfaces.html#interfaces-interface-ethernet-state-mac-address + if state.GetEthernet().GetHwMacAddress() != state.GetEthernet().GetMacAddress() { + log.V(1).Infof("resetting interface %s hw-addr %q", data.hostifDevName, state.GetEthernet().GetHwMacAddress()) + if err := ni.ifaceMgr.SetHWAddr(config.GetName(), state.GetEthernet().GetHwMacAddress()); err != nil { + log.Warningf("Failed to set mac address of port: %v", err) + } + } + } + + if config.GetOrCreateSubinterface(intf.subintf).Enabled != nil { + if state.GetOrCreateSubinterface(intf.subintf).Enabled == nil || config.GetSubinterface(intf.subintf).GetEnabled() != state.GetSubinterface(intf.subintf).GetEnabled() { + log.V(1).Infof("setting interface %s enabled %t", data.hostifDevName, config.GetSubinterface(intf.subintf).GetEnabled()) + _, err := ni.hostifClient.SetHostifAttribute(ctx, &saipb.SetHostifAttributeRequest{ + Oid: data.hostifID, + OperStatus: proto.Bool(config.GetSubinterface(0).GetEnabled()), + }) + if err != nil { + log.Warningf("Failed to set state address of hostif: %v", err) + } + _, err = ni.portClient.SetPortAttribute(ctx, &saipb.SetPortAttributeRequest{ + Oid: data.portID, + AdminState: proto.Bool(config.GetSubinterface(0).GetEnabled()), + }) + if err != nil { + log.Warningf("Failed to set state address of port: %v", err) + } + sb := &ygnmi.SetBatch{} + enabled := config.GetSubinterface(intf.subintf).GetEnabled() && config.GetEnabled() + adminStatus := oc.Interface_AdminStatus_DOWN + if enabled { + adminStatus = oc.Interface_AdminStatus_UP + } + // TODO: Right now treating subinterface 0 and interface as the same. + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Enabled().State(), enabled) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).AdminStatus().State(), adminStatus) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Enabled().State(), enabled) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).AdminStatus().State(), adminStatus) + if _, err := sb.Set(ctx, ni.c); err != nil { + log.Warningf("failed to set link status: %v", err) + } + } + } + + type prefixPair struct { + cfgIP, stateIP *string + cfgPL, statePL *uint8 + } + + // Get all state IPs and their corresponding config IPs (if they exist). + var interfacePairs []*prefixPair + for _, addr := range state.GetOrCreateSubinterface(0).GetOrCreateIpv4().Address { + pair := &prefixPair{ + stateIP: addr.Ip, + statePL: addr.PrefixLength, + } + if pairAddr := config.GetSubinterface(0).GetIpv4().GetAddress(addr.GetIp()); pairAddr != nil { + pair.cfgIP = pairAddr.Ip + pair.cfgPL = pairAddr.PrefixLength + } + interfacePairs = append(interfacePairs, pair) + } + for _, addr := range state.GetOrCreateSubinterface(0).GetOrCreateIpv6().Address { + pair := &prefixPair{ + stateIP: addr.Ip, + statePL: addr.PrefixLength, + } + if pairAddr := config.GetSubinterface(0).GetIpv6().GetAddress(addr.GetIp()); pairAddr != nil { + pair.cfgIP = pairAddr.Ip + pair.cfgPL = pairAddr.PrefixLength + } + interfacePairs = append(interfacePairs, pair) + } + + // Get all config IPs and their corresponding state IPs (if they exist). + for _, addr := range config.GetOrCreateSubinterface(0).GetOrCreateIpv4().Address { + pair := &prefixPair{ + cfgIP: addr.Ip, + cfgPL: addr.PrefixLength, + } + if pairAddr := state.GetSubinterface(0).GetIpv4().GetAddress(addr.GetIp()); pairAddr != nil { + pair.stateIP = pairAddr.Ip + pair.statePL = pairAddr.PrefixLength + } + interfacePairs = append(interfacePairs, pair) + } + for _, addr := range config.GetOrCreateSubinterface(0).GetOrCreateIpv6().Address { + pair := &prefixPair{ + cfgIP: addr.Ip, + cfgPL: addr.PrefixLength, + } + if pairAddr := state.GetSubinterface(0).GetIpv6().GetAddress(addr.GetIp()); pairAddr != nil { + pair.stateIP = pairAddr.Ip + pair.statePL = pairAddr.PrefixLength + } + interfacePairs = append(interfacePairs, pair) + } + + for _, pair := range interfacePairs { + // If an IP exists in state, but not in config, remove the IP. + if (pair.stateIP != nil && pair.statePL != nil) && (pair.cfgIP == nil && pair.cfgPL == nil) { + log.V(1).Infof("Delete Config IP: %v, Config PL: %v. State IP: %v, State PL: %v", pair.cfgIP, pair.cfgPL, *pair.stateIP, *pair.statePL) + log.V(2).Infof("deleting interface %s ip %s/%d", data.hostifDevName, *pair.stateIP, *pair.statePL) + if err := ni.ifaceMgr.DeleteIP(data.hostifDevName, *pair.stateIP, int(*pair.statePL)); err != nil { + log.Warningf("Failed to set ip address of port: %v", err) + } + } + // If an IP exists in config, but not in state (or state is different) add the IP. + if (pair.cfgIP != nil && pair.cfgPL != nil) && (pair.stateIP == nil || *pair.statePL != *pair.cfgPL) { + log.V(1).Infof("Set Config IP: %v, Config PL: %v. State IP: %v, State PL: %v", *pair.cfgIP, *pair.cfgPL, pair.stateIP, pair.statePL) + log.V(2).Infof("setting interface %s ip %s/%d", data.hostifDevName, *pair.cfgIP, *pair.cfgPL) + if err := ni.ifaceMgr.ReplaceIP(data.hostifDevName, *pair.cfgIP, int(*pair.cfgPL)); err != nil { + log.Warningf("Failed to set ip address of port: %v", err) + } + } + } +} + +// getOrCreateInterface returns the state interface from the cache. +func (ni *Reconciler) getOrCreateInterface(iface string) *oc.Interface { + if _, ok := ni.state[iface]; !ok { + ni.state[iface] = &oc.Interface{ + Name: &iface, + } + } + return ni.state[iface] +} + +func (ni *Reconciler) handleDataplaneEvent(ctx context.Context, resp *saipb.PortStateChangeNotificationResponse) { + for _, event := range resp.Data { + log.V(1).Infof("handling dataplane update on: %q", event.String()) + intf, data := ni.ocInterfaceData.findByPortID(event.GetPortId()) + if data == nil { + return + } + operStatus := oc.Interface_OperStatus_UNKNOWN + switch event.PortState { + case saipb.PortOperStatus_PORT_OPER_STATUS_DOWN: + operStatus = oc.Interface_OperStatus_DOWN + case saipb.PortOperStatus_PORT_OPER_STATUS_UP: + operStatus = oc.Interface_OperStatus_UP + } + + sb := &ygnmi.SetBatch{} + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).OperStatus().State(), operStatus) + + if _, err := sb.Set(ctx, ni.c); err != nil { + log.Warningf("failed to set link status: %v", err) + } + } +} + +// handleLinkUpdate modifies the state based on changes to link state. +func (ni *Reconciler) handleLinkUpdate(ctx context.Context, lu *netlink.LinkUpdate) { + ni.stateMu.Lock() + defer ni.stateMu.Unlock() + + log.V(1).Infof("handling link update for %s", lu.Attrs().Name) + + intf, data := ni.ocInterfaceData.findByIfIndex(lu.Attrs().Index) + if data == nil { + return + } + + iface := ni.getOrCreateInterface(intf.name) + _, err := ni.ifaceClient.SetRouterInterfaceAttribute(ctx, &saipb.SetRouterInterfaceAttributeRequest{ + Oid: data.rifID, + SrcMacAddress: lu.Attrs().HardwareAddr, + }) + if err != nil { + log.Warningf("failed to update src mac: %v", err) + } + iface.GetOrCreateEthernet().MacAddress = ygot.String(lu.Attrs().HardwareAddr.String()) + + iface.Ifindex = ygot.Uint32(uint32(lu.Attrs().Index)) + sb := &ygnmi.SetBatch{} + + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Ethernet().MacAddress().State(), *iface.Ethernet.MacAddress) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Ifindex().State(), *iface.Ifindex) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ifindex().State(), *iface.Ifindex) + if _, err := sb.Set(ctx, ni.c); err != nil { + log.Warningf("failed to set link status: %v", err) + } +} + +// handleAddrUpdate modifies the state based on changes to addresses. +func (ni *Reconciler) handleAddrUpdate(ctx context.Context, au *netlink.AddrUpdate) { + ni.stateMu.Lock() + defer ni.stateMu.Unlock() + + intf, data := ni.ocInterfaceData.findByIfIndex(au.LinkIndex) + if data == nil { + return + } + + sb := &ygnmi.SetBatch{} + sub := ni.getOrCreateInterface(intf.name).GetOrCreateSubinterface(intf.subintf) + + ip := au.LinkAddress.IP.String() + ipBytes := au.LinkAddress.IP.To4() + mask := net.CIDRMask(32, 32) + if ipBytes == nil { + ipBytes = au.LinkAddress.IP.To16() + mask = net.CIDRMask(128, 128) + } + pl, _ := au.LinkAddress.Mask.Size() + isV4 := au.LinkAddress.IP.To4() != nil + + entry := fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST).WithBytes(ipBytes))) + + log.V(1).Infof("handling addr update for %s ip %v pl %v", data.hostifDevName, ip, pl) + // The dataplane does not monitor the local interface's IP addr, they must set externally. + if au.NewAddr { + if isV4 { + sub.GetOrCreateIpv4().GetOrCreateAddress(ip).PrefixLength = ygot.Uint8(uint8(pl)) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Address(ip).Ip().State(), au.LinkAddress.IP.String()) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Address(ip).PrefixLength().State(), uint8(pl)) + } else { + sub.GetOrCreateIpv6().GetOrCreateAddress(ip).PrefixLength = ygot.Uint8(uint8(pl)) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Address(ip).Ip().State(), au.LinkAddress.IP.String()) + gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Address(ip).PrefixLength().State(), uint8(pl)) + } + _, err := ni.fwdClient.TableEntryAdd(ctx, fwdconfig.TableEntryAddRequest(ni.contextID, cpusink.IP2MeTable). + AppendEntry(entry, fwdconfig.Action(fwdconfig.TransmitAction(fmt.Sprint(data.hostifID)))).Build()) + if err != nil { + log.Warningf("failed to add route: %v", err) + return + } + _, err = ni.routeClient.CreateRouteEntry(ctx, &saipb.CreateRouteEntryRequest{ + Entry: &saipb.RouteEntry{ + SwitchId: ni.switchID, + VrId: 0, + Destination: &saipb.IpPrefix{Addr: ipBytes, Mask: mask}, + }, + NextHopId: proto.Uint64(ni.cpuPortID), + PacketAction: saipb.PacketAction_PACKET_ACTION_FORWARD.Enum(), + }) + if err != nil { + log.Warningf("failed to add route: %v", err) + return + } + } else { + if isV4 { + sub.GetOrCreateIpv4().DeleteAddress(ip) + gnmiclient.BatchDelete(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Address(ip).State()) + } else { + sub.GetOrCreateIpv6().DeleteAddress(ip) + gnmiclient.BatchDelete(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Address(ip).State()) + } + _, err := ni.fwdClient.TableEntryRemove(ctx, &fwdpb.TableEntryRemoveRequest{ + ContextId: &fwdpb.ContextId{Id: ni.contextID}, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: cpusink.IP2MeTable}}, + EntryDesc: entry.Build(), + }) + if err != nil { + log.Warningf("failed to remove route: %v", err) + return + } + _, err = ni.routeClient.RemoveRouteEntry(ctx, &saipb.RemoveRouteEntryRequest{ + Entry: &saipb.RouteEntry{ + SwitchId: ni.switchID, + VrId: 0, + Destination: &saipb.IpPrefix{Addr: ipBytes, Mask: mask}, + }, + }) + if err != nil { + log.Warningf("failed to remove route: %v", err) + return + } + } + if _, err := sb.Set(ctx, ni.c); err != nil { + log.Warningf("failed to set link status: %v", err) + } +} + +// handleNeighborUpdate modifies the state based on changes to the neighbor. +func (ni *Reconciler) handleNeighborUpdate(ctx context.Context, nu *netlink.NeighUpdate) { + ni.stateMu.Lock() + defer ni.stateMu.Unlock() + log.V(1).Infof("handling neighbor update for %s on %d", nu.IP.String(), nu.LinkIndex) + + intf, data := ni.ocInterfaceData.findByIfIndex(nu.LinkIndex) + if data == nil { + return + } + + sb := &ygnmi.SetBatch{} + sub := ni.getOrCreateInterface(intf.name).GetOrCreateSubinterface(intf.subintf) + + switch nu.Type { + case unix.RTM_DELNEIGH: + _, err := ni.neighborClient.RemoveNeighborEntry(ctx, &saipb.RemoveNeighborEntryRequest{ + Entry: &saipb.NeighborEntry{ + SwitchId: ni.switchID, + RifId: data.rifID, + IpAddress: ipToBytes(nu.IP), + }, + }) + if err != nil { + log.Warningf("failed to remove neighbor to dataplane: %v", err) + return + } + if nu.Family == unix.AF_INET6 { + sub.GetOrCreateIpv6().DeleteNeighbor(nu.IP.String()) + gnmiclient.BatchDelete(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Neighbor(nu.IP.String()).State()) + } else { + sub.GetOrCreateIpv4().DeleteNeighbor(nu.IP.String()) + gnmiclient.BatchDelete(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Neighbor(nu.IP.String()).State()) + } + case unix.RTM_NEWNEIGH: + if len(nu.HardwareAddr) == 0 { + log.Info("skipping neighbor update with no hwaddr") + return + } + _, err := ni.neighborClient.CreateNeighborEntry(ctx, &saipb.CreateNeighborEntryRequest{ + Entry: &saipb.NeighborEntry{ + SwitchId: ni.switchID, + RifId: data.rifID, + IpAddress: ipToBytes(nu.IP), + }, + DstMacAddress: nu.HardwareAddr, + }) + if err != nil { + log.Warningf("failed to create neighbor entry: %v", err) + } + if nu.Family == unix.AF_INET6 { + neigh := sub.GetOrCreateIpv6().GetOrCreateNeighbor(nu.IP.String()) + neigh.LinkLayerAddress = ygot.String(nu.HardwareAddr.String()) + if nu.Flags&unix.NUD_PERMANENT != 0 { + neigh.Origin = oc.IfIp_NeighborOrigin_STATIC + } else { + neigh.Origin = oc.IfIp_NeighborOrigin_DYNAMIC + } + gnmiclient.BatchReplace(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Neighbor(nu.IP.String()).Ip().State(), neigh.GetIp()) + gnmiclient.BatchReplace(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Neighbor(nu.IP.String()).LinkLayerAddress().State(), neigh.GetLinkLayerAddress()) + gnmiclient.BatchReplace(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv6().Neighbor(nu.IP.String()).Origin().State(), neigh.GetOrigin()) + } else { + neigh := sub.GetOrCreateIpv4().GetOrCreateNeighbor(nu.IP.String()) + neigh.LinkLayerAddress = ygot.String(nu.HardwareAddr.String()) + if nu.Flags&unix.NUD_PERMANENT != 0 { + neigh.Origin = oc.IfIp_NeighborOrigin_STATIC + } else { + neigh.Origin = oc.IfIp_NeighborOrigin_DYNAMIC + } + gnmiclient.BatchReplace(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Neighbor(nu.IP.String()).Ip().State(), neigh.GetIp()) + gnmiclient.BatchReplace(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Neighbor(nu.IP.String()).LinkLayerAddress().State(), neigh.GetLinkLayerAddress()) + gnmiclient.BatchReplace(sb, ocpath.Root().Interface(intf.name).Subinterface(intf.subintf).Ipv4().Neighbor(nu.IP.String()).Origin().State(), neigh.GetOrigin()) + } + default: + log.Warningf("unknown neigh update type: %v", nu.Type) + } + + if _, err := sb.Set(ctx, ni.c); err != nil { + log.Warningf("failed to set link status: %v", err) + } +} + +const ( + internalSuffix = "-internal" +) + +// setupPorts creates the dataplane ports and TAP interfaces for all interfaces on the device. +func (ni *Reconciler) setupPorts(ctx context.Context) error { + ifs, err := ni.ifaceMgr.GetAll() + if err != nil { + return err + } + + for _, i := range ifs { + // Skip loopback, k8s pod interface, and tap interfaces. + if i.Name == "lo" || i.Name == "eth0" || strings.HasSuffix(i.Name, internalSuffix) { + continue + } + log.Info("creating interfaces for %v", i.Name) + ocIntf := ocInterface{ + name: i.Name, + subintf: 0, + } + data := &interfaceData{} + + portResp, err := ni.portClient.CreatePort(ctx, &saipb.CreatePortRequest{ + Switch: ni.switchID, + }) + if err != nil { + return fmt.Errorf("failed to create port %q: %w", i.Name, err) + } + data.portID = portResp.Oid + + hostifName := i.Name + internalSuffix + hostifResp, err := ni.hostifClient.CreateHostif(ctx, &saipb.CreateHostifRequest{ + Switch: ni.switchID, + Type: saipb.HostifType_HOSTIF_TYPE_NETDEV.Enum(), + ObjId: &portResp.Oid, + Name: []byte(hostifName), + OperStatus: proto.Bool(true), + }) + if err != nil { + return fmt.Errorf("failed to create host interface %q: %w", hostifName, err) + } + data.hostifID = hostifResp.Oid + data.hostifDevName = hostifName + + tap, err := ni.ifaceMgr.GetByName(hostifName) + if err != nil { + return fmt.Errorf("failed to find tap interface %q: %w", hostifName, err) + } + data.hostifIfIndex = tap.Index + + rifResp, err := ni.ifaceClient.CreateRouterInterface(ctx, &saipb.CreateRouterInterfaceRequest{ + Switch: ni.switchID, + Type: saipb.RouterInterfaceType_ROUTER_INTERFACE_TYPE_PORT.Enum(), + PortId: &portResp.Oid, + SrcMacAddress: tap.HardwareAddr, + VirtualRouterId: proto.Uint64(0), + }) + if err != nil { + return fmt.Errorf("failed to update MAC address for interface %q: %w", i.Name, err) + } + data.rifID = rifResp.Oid + ni.getOrCreateInterface(i.Name).GetOrCreateEthernet().SetHwMacAddress(tap.HardwareAddr.String()) + ni.getOrCreateInterface(i.Name).GetOrCreateEthernet().SetMacAddress(tap.HardwareAddr.String()) + if _, err := gnmiclient.Update(ctx, ni.c, ocpath.Root().Interface(i.Name).Ethernet().HwMacAddress().State(), tap.HardwareAddr.String()); err != nil { + return fmt.Errorf("failed to set hw addr of interface %q: %v", tap.Name, err) + } + if _, err := gnmiclient.Update(ctx, ni.c, ocpath.Root().Interface(i.Name).Ethernet().MacAddress().State(), tap.HardwareAddr.String()); err != nil { + return fmt.Errorf("failed to set hw addr of interface %q: %v", tap.Name, err) + } + ni.ocInterfaceData[ocIntf] = data + } + return nil +} + +// ipToBytes converts a net.IP to a slice of bytes of the correct length (4 for IPv4, 16 for IPv6). +func ipToBytes(ip net.IP) []byte { + if ip.To4() != nil { + return ip.To4() + } + return ip.To16() +} diff --git a/dataplane/dplanerc/routes.go b/dataplane/dplanerc/routes.go new file mode 100644 index 00000000..5a94f8b9 --- /dev/null +++ b/dataplane/dplanerc/routes.go @@ -0,0 +1,257 @@ +// Copyright 2022 Google LLC +// +// 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 dplanerc + +import ( + "context" + "encoding/binary" + "fmt" + "net" + "net/netip" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/openconfig/ygnmi/schemaless" + "github.com/openconfig/ygnmi/ygnmi" + "google.golang.org/protobuf/proto" + + "github.com/openconfig/lemming/gnmi" + + log "github.com/golang/glog" + + "github.com/openconfig/lemming/dataplane/internal/engine" + saipb "github.com/openconfig/lemming/dataplane/standalone/proto" + dpb "github.com/openconfig/lemming/proto/dataplane" + fwdpb "github.com/openconfig/lemming/proto/forwarding" +) + +// RouteQuery returns a ygnmi query for a route with the given prefix and vrf. +func RouteQuery(ni string, prefix string) ygnmi.ConfigQuery[*dpb.Route] { + q, err := schemaless.NewConfig[*dpb.Route](fmt.Sprintf("/dataplane/routes/route[prefix=%s][vrf=%s]", prefix, ni), gnmi.InternalOrigin) + if err != nil { + log.Fatal(err) + } + return q +} + +// MustWildcardQuery returns a wildcard card query for all routes. +func MustWildcardQuery() ygnmi.WildcardQuery[*dpb.Route] { + q, err := schemaless.NewWildcard[*dpb.Route]("/dataplane/routes/route[prefix=*][vrf=*]", gnmi.InternalOrigin) + if err != nil { + log.Fatal(err) + } + return q +} + +func (ni *Reconciler) StartRoute(ctx context.Context, client *ygnmi.Client) error { + ctx, cancelFn := context.WithCancel(ctx) + w := ygnmi.WatchAll(ctx, client, MustWildcardQuery(), func(v *ygnmi.Value[*dpb.Route]) error { + route, present := v.Val() + prefix, err := netip.ParsePrefix(v.Path.Elem[2].Key["prefix"]) + if err != nil { + log.Warningf("failed to parse cidr: %v", err) + return ygnmi.Continue + } + ipBytes := prefix.Masked().Addr().AsSlice() + mask := net.CIDRMask(prefix.Bits(), len(ipBytes)*8) + + entry := &saipb.RouteEntry{ + SwitchId: ni.switchID, + VrId: 0, // TODO: support vrf-ids other than 0. + Destination: &saipb.IpPrefix{ + Addr: ipBytes, + Mask: mask, + }, + } + + if !present { + log.Infof("removing route: %v", prefix) + _, err := ni.routeClient.RemoveRouteEntry(ctx, &saipb.RemoveRouteEntryRequest{ + Entry: entry, + }) + if err != nil { + log.Warningf("failed to delete route: %v", err) + } + return ygnmi.Continue + } + rReq := saipb.CreateRouteEntryRequest{ + Entry: entry, + PacketAction: saipb.PacketAction_PACKET_ACTION_FORWARD.Enum(), + } + + if route.GetInterface() != nil { // If next hop is a interface. + // TODO: Add support for subinterfaces. + data := ni.ocInterfaceData[ocInterface{name: route.GetInterface().GetInterface(), subintf: route.GetInterface().GetSubinterface()}] + rReq.NextHopId = &data.rifID + + if _, err := ni.routeClient.CreateRouteEntry(ctx, &rReq); err != nil { + log.Warningf("failed to create route: %v", err) + } + log.Infof("added connected route: %v", &rReq) + return ygnmi.Continue + } + var hopID uint64 + if len(route.GetNextHops().GetHops()) == 1 { + hopID, err = ni.createNextHop(ctx, route.GetNextHops().Hops[0]) + if err != nil { + log.Warningf("failed to create next hop: %v", err) + return ygnmi.Continue + } + } else { + group, err := ni.nextHopGroupClient.CreateNextHopGroup(ctx, &saipb.CreateNextHopGroupRequest{ + Switch: ni.switchID, + Type: saipb.NextHopGroupType_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP.Enum(), + }) + hopID = group.Oid + if err != nil { + log.Warningf("failed to create next hop group: %v", err) + return ygnmi.Continue + } + for i, nh := range route.GetNextHops().GetHops() { + hopID, err = ni.createNextHop(ctx, nh) + if err != nil { + log.Warningf("failed to create next hop: %v", err) + return ygnmi.Continue + } + _, err = ni.nextHopGroupClient.CreateNextHopGroupMember(ctx, &saipb.CreateNextHopGroupMemberRequest{ + Switch: ni.switchID, + NextHopGroupId: &group.Oid, + NextHopId: &hopID, + Weight: proto.Uint32(uint32(route.GetNextHops().Weights[i])), + }) + if err != nil { + log.Warningf("failed to create next group member: %v", err) + return ygnmi.Continue + } + } + } + rReq.NextHopId = proto.Uint64(hopID) + if _, err := ni.routeClient.CreateRouteEntry(ctx, &rReq); err != nil { + log.Warningf("failed to create route: %v", err) + return ygnmi.Continue + } + log.Infof("created route entry: %v", &rReq) + + return ygnmi.Continue + }) + go func() { + // TODO: handle error + if _, err := w.Await(); err != nil { + log.Warningf("routes watch err: %v", err) + } + }() + ni.closers = append(ni.closers, cancelFn) + return nil +} + +func (ni *Reconciler) createNextHop(ctx context.Context, hop *dpb.NextHop) (uint64, error) { + ip, err := netip.ParseAddr(hop.GetNextHopIp()) + if err != nil { + return 0, err + } + data := ni.ocInterfaceData[ocInterface{name: hop.GetInterface().GetInterface(), subintf: hop.GetInterface().GetSubinterface()}] + hopReq := saipb.CreateNextHopRequest{ + Switch: ni.switchID, + Type: saipb.NextHopType_NEXT_HOP_TYPE_IP.Enum(), + Ip: ip.AsSlice(), + RouterInterfaceId: proto.Uint64(data.rifID), + } + resp, err := ni.nextHopClient.CreateNextHop(ctx, &hopReq) + if err != nil { + return 0, err + } + log.Infof("created next hop: %v", &hopReq) + if hop.GetGue() != nil { + acts, err := gueActions(hop.GetGue()) + if err != nil { + return 0, err + } + actReq := &fwdpb.TableEntryAddRequest{ + ContextId: &fwdpb.ContextId{Id: ni.contextID}, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: engine.NHActionTable}}, + EntryDesc: &fwdpb.EntryDesc{Entry: &fwdpb.EntryDesc_Exact{ + Exact: &fwdpb.ExactEntryDesc{ + Fields: []*fwdpb.PacketFieldBytes{{ + FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID}}, + Bytes: binary.BigEndian.AppendUint64(nil, resp.Oid), + }}, + }, + }}, + Actions: acts, + } + // TODO: Ideally, this would use the SAI tunnel, but it's not currently supported. + _, err = ni.fwdClient.TableEntryAdd(ctx, actReq) + if err != nil { + return 0, err + } + log.Infof("created gue actions: %v", actReq) + } + return resp.Oid, nil +} + +func gueActions(gueHeaders *dpb.GUE) ([]*fwdpb.ActionDesc, error) { + var ip gopacket.SerializableLayer + var headerID fwdpb.PacketHeaderId + if !gueHeaders.IsV6 { + ip = &layers.IPv4{ + Version: 4, + IHL: 5, + Protocol: layers.IPProtocolUDP, + SrcIP: gueHeaders.SrcIp, + DstIP: gueHeaders.DstIp, + } + headerID = fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4 + } else { + ip = &layers.IPv6{ + Version: 6, + NextHeader: layers.IPProtocolUDP, + SrcIP: gueHeaders.SrcIp, + DstIP: gueHeaders.DstIp, + } + headerID = fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP6 + } + + udp := &layers.UDP{ + SrcPort: 0, // TODO(wenbli): Implement hashing for srcPort. + Length: 34, // TODO(wenbli): Figure out how to not make this hardcoded. + } + udp.DstPort = layers.UDPPort(gueHeaders.DstPort) + buf := gopacket.NewSerializeBuffer() + if err := gopacket.SerializeLayers(buf, gopacket.SerializeOptions{}, ip, udp); err != nil { + return nil, fmt.Errorf("failed to serialize GUE headers: %v", err) + } + + return []*fwdpb.ActionDesc{{ + ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, + Action: &fwdpb.ActionDesc_Reparse{ + Reparse: &fwdpb.ReparseActionDesc{ + HeaderId: headerID, + FieldIds: []*fwdpb.PacketFieldId{ // Copy all metadata fields. + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_INPUT_IFACE}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TRAP_ID}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID}}, + {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_VRF}}, + }, + // After the UDP header, the rest of the packet (original packet) will be classified as payload. + Prepend: buf.Bytes(), + }, + }, + }}, nil +} diff --git a/dataplane/forwarding/protocol/metadata/metadata.go b/dataplane/forwarding/protocol/metadata/metadata.go index 37b22ce9..730fb95e 100644 --- a/dataplane/forwarding/protocol/metadata/metadata.go +++ b/dataplane/forwarding/protocol/metadata/metadata.go @@ -118,6 +118,8 @@ func (m *Metadata) Field(id fwdpacket.FieldID) ([]byte, error) { return m.inputIface, nil case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE: return m.outputIface, nil + case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TRAP_ID: + return m.trapID, nil default: return nil, fmt.Errorf("metadata: Field %v failed, unsupported field", id) diff --git a/dataplane/handlers/interface.go b/dataplane/handlers/interface.go deleted file mode 100644 index 20495a73..00000000 --- a/dataplane/handlers/interface.go +++ /dev/null @@ -1,626 +0,0 @@ -// Copyright 2022 Google LLC -// -// 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. - -//go:build linux - -// Package handlers contains gNMI task handlers. -package handlers - -import ( - "context" - "fmt" - "net" - "strings" - "sync" - "time" - - "github.com/openconfig/ygnmi/ygnmi" - "github.com/openconfig/ygot/ygot" - "github.com/vishvananda/netlink" - "golang.org/x/sys/unix" - - "github.com/openconfig/lemming/dataplane/internal/engine" - "github.com/openconfig/lemming/dataplane/internal/kernel" - "github.com/openconfig/lemming/gnmi/gnmiclient" - "github.com/openconfig/lemming/gnmi/oc" - "github.com/openconfig/lemming/gnmi/oc/ocpath" - "github.com/openconfig/lemming/gnmi/reconciler" - - log "github.com/golang/glog" - - dpb "github.com/openconfig/lemming/proto/dataplane" - fwdpb "github.com/openconfig/lemming/proto/forwarding" -) - -// Interface handles config updates to the /interfaces/... paths. -type Interface struct { - c *ygnmi.Client - // closers functions should all be invoked when the interface handler stops running. - closers []func() - e *engine.Engine - stateMu sync.RWMutex - // state keeps track of the applied state of the device's interfaces so that we do not issue duplicate configuration commands to the device's interfaces. - state map[string]*oc.Interface - idxToName map[int]string - internalToExternalPort map[string]string - externalToInternalPort map[string]string - ifaceMgr interfaceManager -} - -type interfaceManager interface { - SetHWAddr(name string, addr string) error - SetState(name string, up bool) error - ReplaceIP(name string, ip string, prefixLen int) error - DeleteIP(name string, ip string, prefixLen int) error - GetAll() ([]net.Interface, error) - GetByName(name string) (*net.Interface, error) - CreateTAP(name string) (int, error) - LinkSubscribe(ch chan<- netlink.LinkUpdate, done <-chan struct{}) error - AddrSubscribe(ch chan<- netlink.AddrUpdate, done <-chan struct{}) error - NeighSubscribe(ch chan<- netlink.NeighUpdate, done <-chan struct{}) error -} - -// NewInterface creates a new interface handler. -func NewInterface(e *engine.Engine) *reconciler.BuiltReconciler { - i := &Interface{ - e: e, - idxToName: map[int]string{}, - state: map[string]*oc.Interface{}, - ifaceMgr: &kernel.Interfaces{}, - internalToExternalPort: map[string]string{}, - externalToInternalPort: map[string]string{}, - } - return reconciler.NewBuilder("interface").WithStart(i.start).WithStop(i.stop).Build() -} - -// Start starts running the handler, watching the cache and the kernel interfaces. -func (ni *Interface) start(ctx context.Context, client *ygnmi.Client) error { - log.Info("starting interface handler") - b := &ocpath.Batch{} - ni.c = client - - if err := ni.setupPorts(ctx); err != nil { - return fmt.Errorf("failed to setup ports: %v", err) - } - - b.AddPaths( - ocpath.Root().InterfaceAny().Name().Config().PathStruct(), - ocpath.Root().InterfaceAny().Ethernet().MacAddress().Config().PathStruct(), - ocpath.Root().InterfaceAny().Subinterface(0).Enabled().Config().PathStruct(), // TODO: Do we need enable at root interface level? - ocpath.Root().InterfaceAny().Subinterface(0).Ipv4().AddressAny().Ip().Config().PathStruct(), - ocpath.Root().InterfaceAny().Subinterface(0).Ipv4().AddressAny().PrefixLength().Config().PathStruct(), - ocpath.Root().InterfaceAny().Subinterface(0).Ipv6().AddressAny().Ip().Config().PathStruct(), - ocpath.Root().InterfaceAny().Subinterface(0).Ipv6().AddressAny().PrefixLength().Config().PathStruct(), - ) - cancelCtx, cancelFn := context.WithCancel(ctx) - - watcher := ygnmi.Watch(cancelCtx, ni.c, b.Config(), func(val *ygnmi.Value[*oc.Root]) error { - log.V(2).Info("reconciling interfaces") - root, ok := val.Val() - if !ok || root.Interface == nil { - return ygnmi.Continue - } - for _, i := range root.Interface { - ni.reconcile(i) - } - return ygnmi.Continue - }) - - linkDoneCh := make(chan struct{}) - linkUpdateCh := make(chan netlink.LinkUpdate) - addrDoneCh := make(chan struct{}) - addrUpdateCh := make(chan netlink.AddrUpdate) - neighDoneCh := make(chan struct{}) - neighUpdateCh := make(chan netlink.NeighUpdate) - ni.closers = append(ni.closers, func() { - close(linkDoneCh) - close(addrDoneCh) - close(neighDoneCh) - }, cancelFn) - - if err := ni.ifaceMgr.LinkSubscribe(linkUpdateCh, linkDoneCh); err != nil { - return fmt.Errorf("failed to sub to link: %v", err) - } - if err := ni.ifaceMgr.AddrSubscribe(addrUpdateCh, addrDoneCh); err != nil { - return fmt.Errorf("failed to sub to addr: %v", err) - } - if err := ni.ifaceMgr.NeighSubscribe(neighUpdateCh, addrDoneCh); err != nil { - return fmt.Errorf("failed to sub to neighbor: %v", err) - } - // TODO: Decide if this needs another layer of abstraction. Currently, one notification callback is allowed. - if err := ni.e.Server.UpdateNotification(&fwdpb.ContextId{Id: ni.e.ID()}, func(ed *fwdpb.EventDesc) { ni.handleDataplaneEvent(ctx, ed) }); err != nil { - return fmt.Errorf("failed to sub to dataplane: %v", err) - } - - go func() { - for { - select { - case up := <-linkUpdateCh: - ni.handleLinkUpdate(ctx, &up) - case up := <-addrUpdateCh: - ni.handleAddrUpdate(ctx, &up) - case up := <-neighUpdateCh: - ni.handleNeighborUpdate(ctx, &up) - } - } - }() - - go func() { - // TODO: handle error - if _, err := watcher.Await(); err != nil { - log.Warningf("interface watch err: %v", err) - } - }() - - ni.startCounterUpdates(ctx) - - return nil -} - -// Stop stops all watchers. -func (ni *Interface) stop(context.Context) error { - // TODO: prevent stopping more than once. - for _, closeFn := range ni.closers { - closeFn() - } - return nil -} - -// startCounterUpdates starts a goroutine for updating counters for configured -// interfaces. -func (ni *Interface) startCounterUpdates(ctx context.Context) { - tick := time.NewTicker(time.Second) - ni.closers = append(ni.closers, tick.Stop) - go func() { - // Design comment: - // This polling can be eliminated if either the forwarding - // service supported streaming the counters, or if somehow the - // gnmi cache were able to forward queries to prompt the data - // producer to populate the leaf. - // - // However, given counters are likely frequently-updated values - // anyways, it may be fine for counter values to be polled. - for range tick.C { - ni.stateMu.RLock() - var intfNames []string - for intfName := range ni.state { - // TODO(wenbli): Support interface state deletion when interface is deleted. - intfNames = append(intfNames, intfName) - } - ni.stateMu.RUnlock() - for _, intfName := range intfNames { - countersReply, err := ni.e.GetCounters(ctx, intfName) - log.V(2).Infof("querying counters for interface %q, got %v", intfName, countersReply) - if err != nil { - log.Errorf("interface handler: could not retrieve counter for interface %q", intfName) - continue - } - for _, counter := range countersReply.Counters { - switch counter.Id { - case fwdpb.CounterId_COUNTER_ID_RX_PACKETS: - // TODO(wenbli): Perhaps should make a logging version of ygnmi. - if _, err := gnmiclient.Replace(ctx, ni.c, ocpath.Root().Interface(intfName).Counters().InPkts().State(), counter.Value); err != nil { - log.Errorf("interface handler: %v", err) - } - case fwdpb.CounterId_COUNTER_ID_TX_PACKETS: - if _, err := gnmiclient.Replace(ctx, ni.c, ocpath.Root().Interface(intfName).Counters().OutPkts().State(), counter.Value); err != nil { - log.Errorf("interface handler: %v", err) - } - } - } - } - } - }() -} - -// reconcile compares the interface config with state and modifies state to match config. -func (ni *Interface) reconcile(config *oc.Interface) { - ni.stateMu.RLock() - defer ni.stateMu.RUnlock() - - tapName := ni.externalToInternalPort[config.GetName()] - state := ni.getOrCreateInterface(config.GetName()) - - if config.GetOrCreateEthernet().MacAddress != nil { - if config.GetEthernet().GetMacAddress() != state.GetEthernet().GetMacAddress() { - log.V(1).Infof("setting interface %s hw-addr %q", tapName, config.GetEthernet().GetMacAddress()) - if err := ni.ifaceMgr.SetHWAddr(config.GetName(), config.GetEthernet().GetMacAddress()); err != nil { - log.Warningf("Failed to set mac address of port: %v", err) - } - } - } else { - // Deleting the configured MAC address means it should be the system-assigned MAC address, as detailed in the OpenConfig schema. - // https://openconfig.net/projects/models/schemadocs/yangdoc/openconfig-interfaces.html#interfaces-interface-ethernet-state-mac-address - if state.GetEthernet().GetHwMacAddress() != state.GetEthernet().GetMacAddress() { - log.V(1).Infof("resetting interface %s hw-addr %q", tapName, state.GetEthernet().GetHwMacAddress()) - if err := ni.ifaceMgr.SetHWAddr(config.GetName(), state.GetEthernet().GetHwMacAddress()); err != nil { - log.Warningf("Failed to set mac address of port: %v", err) - } - } - } - - if config.GetOrCreateSubinterface(0).Enabled != nil { - if state.GetOrCreateSubinterface(0).Enabled == nil || config.GetSubinterface(0).GetEnabled() != state.GetSubinterface(0).GetEnabled() { - log.V(1).Infof("setting interface %s enabled %t", tapName, config.GetSubinterface(0).GetEnabled()) - state := fwdpb.PortState_PORT_STATE_DISABLED_DOWN - if config.GetSubinterface(0).GetEnabled() { - state = fwdpb.PortState_PORT_STATE_ENABLED_UP - } - _, err := ni.e.PortState(context.Background(), &fwdpb.PortStateRequest{ - ContextId: &fwdpb.ContextId{Id: ni.e.ID()}, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: tapName}}, - Operation: &fwdpb.PortInfo{AdminStatus: state}, - }) - if err != nil { - log.Warningf("Failed to set state address of port: %v", err) - } - } - } - - type prefixPair struct { - cfgIP, stateIP *string - cfgPL, statePL *uint8 - } - - // Get all state IPs and their corresponding config IPs (if they exist). - var interfacePairs []*prefixPair - for _, addr := range state.GetOrCreateSubinterface(0).GetOrCreateIpv4().Address { - pair := &prefixPair{ - stateIP: addr.Ip, - statePL: addr.PrefixLength, - } - if pairAddr := config.GetSubinterface(0).GetIpv4().GetAddress(addr.GetIp()); pairAddr != nil { - pair.cfgIP = pairAddr.Ip - pair.cfgPL = pairAddr.PrefixLength - } - interfacePairs = append(interfacePairs, pair) - } - for _, addr := range state.GetOrCreateSubinterface(0).GetOrCreateIpv6().Address { - pair := &prefixPair{ - stateIP: addr.Ip, - statePL: addr.PrefixLength, - } - if pairAddr := config.GetSubinterface(0).GetIpv6().GetAddress(addr.GetIp()); pairAddr != nil { - pair.cfgIP = pairAddr.Ip - pair.cfgPL = pairAddr.PrefixLength - } - interfacePairs = append(interfacePairs, pair) - } - - // Get all config IPs and their corresponding state IPs (if they exist). - for _, addr := range config.GetOrCreateSubinterface(0).GetOrCreateIpv4().Address { - pair := &prefixPair{ - cfgIP: addr.Ip, - cfgPL: addr.PrefixLength, - } - if pairAddr := state.GetSubinterface(0).GetIpv4().GetAddress(addr.GetIp()); pairAddr != nil { - pair.stateIP = pairAddr.Ip - pair.statePL = pairAddr.PrefixLength - } - interfacePairs = append(interfacePairs, pair) - } - for _, addr := range config.GetOrCreateSubinterface(0).GetOrCreateIpv6().Address { - pair := &prefixPair{ - cfgIP: addr.Ip, - cfgPL: addr.PrefixLength, - } - if pairAddr := state.GetSubinterface(0).GetIpv6().GetAddress(addr.GetIp()); pairAddr != nil { - pair.stateIP = pairAddr.Ip - pair.statePL = pairAddr.PrefixLength - } - interfacePairs = append(interfacePairs, pair) - } - - for _, pair := range interfacePairs { - // If an IP exists in state, but not in config, remove the IP. - if (pair.stateIP != nil && pair.statePL != nil) && (pair.cfgIP == nil && pair.cfgPL == nil) { - log.V(1).Infof("Delete Config IP: %v, Config PL: %v. State IP: %v, State PL: %v", pair.cfgIP, pair.cfgPL, *pair.stateIP, *pair.statePL) - log.V(2).Infof("deleting interface %s ip %s/%d", tapName, *pair.stateIP, *pair.statePL) - if err := ni.ifaceMgr.DeleteIP(tapName, *pair.stateIP, int(*pair.statePL)); err != nil { - log.Warningf("Failed to set ip address of port: %v", err) - } - } - // If an IP exists in config, but not in state (or state is different) add the IP. - if (pair.cfgIP != nil && pair.cfgPL != nil) && (pair.stateIP == nil || *pair.statePL != *pair.cfgPL) { - log.V(1).Infof("Set Config IP: %v, Config PL: %v. State IP: %v, State PL: %v", *pair.cfgIP, *pair.cfgPL, pair.stateIP, pair.statePL) - log.V(2).Infof("setting interface %s ip %s/%d", tapName, *pair.cfgIP, *pair.cfgPL) - if err := ni.ifaceMgr.ReplaceIP(tapName, *pair.cfgIP, int(*pair.cfgPL)); err != nil { - log.Warningf("Failed to set ip address of port: %v", err) - } - } - } -} - -// getOrCreateInterface returns the state interface from the cache. -func (ni *Interface) getOrCreateInterface(iface string) *oc.Interface { - if _, ok := ni.state[iface]; !ok { - ni.state[iface] = &oc.Interface{ - Name: &iface, - } - } - return ni.state[iface] -} - -func (ni *Interface) handleDataplaneEvent(ctx context.Context, ed *fwdpb.EventDesc) { - if ed.Event != fwdpb.Event_EVENT_PORT { - return - } - desc := ed.Desc.(*fwdpb.EventDesc_Port).Port - log.V(1).Infof("handling dataplane update on: %q", desc.GetPortId().GetObjectId().GetId()) - modelName, ok := ni.internalToExternalPort[desc.GetPortId().GetObjectId().GetId()] - if !ok { - return - } - operStatus := oc.Interface_OperStatus_UNKNOWN - enabled := false - adminStatus := oc.Interface_AdminStatus_UNSET - switch desc.PortInfo.OperStatus { - case fwdpb.PortState_PORT_STATE_ENABLED_UP: - operStatus = oc.Interface_OperStatus_UP - case fwdpb.PortState_PORT_STATE_DISABLED_DOWN: - operStatus = oc.Interface_OperStatus_DOWN - } - switch desc.PortInfo.AdminStatus { - case fwdpb.PortState_PORT_STATE_ENABLED_UP: - enabled = true - adminStatus = oc.Interface_AdminStatus_UP - case fwdpb.PortState_PORT_STATE_DISABLED_DOWN: - adminStatus = oc.Interface_AdminStatus_DOWN - } - - sb := &ygnmi.SetBatch{} - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Enabled().State(), enabled) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).OperStatus().State(), operStatus) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).AdminStatus().State(), adminStatus) - - if _, err := sb.Set(ctx, ni.c); err != nil { - log.Warningf("failed to set link status: %v", err) - } -} - -// handleLinkUpdate modifies the state based on changes to link state. -func (ni *Interface) handleLinkUpdate(ctx context.Context, lu *netlink.LinkUpdate) { - ni.stateMu.Lock() - defer ni.stateMu.Unlock() - - log.V(1).Infof("handling link update for %s", lu.Attrs().Name) - - modelName, ok := ni.internalToExternalPort[lu.Attrs().Name] - if !ok { - return - } - - iface := ni.getOrCreateInterface(modelName) - if err := ni.e.UpdatePortSrcMAC(ctx, modelName, lu.Attrs().HardwareAddr); err != nil { - log.Warningf("failed to update src mac: %v", err) - } - iface.GetOrCreateEthernet().MacAddress = ygot.String(lu.Attrs().HardwareAddr.String()) - - iface.Ifindex = ygot.Uint32(uint32(lu.Attrs().Index)) - sb := &ygnmi.SetBatch{} - - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Ethernet().MacAddress().State(), *iface.Ethernet.MacAddress) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Ifindex().State(), *iface.Ifindex) - if _, err := sb.Set(ctx, ni.c); err != nil { - log.Warningf("failed to set link status: %v", err) - } -} - -// handleAddrUpdate modifies the state based on changes to addresses. -func (ni *Interface) handleAddrUpdate(ctx context.Context, au *netlink.AddrUpdate) { - ni.stateMu.Lock() - defer ni.stateMu.Unlock() - name := ni.idxToName[au.LinkIndex] - - modelName, ok := ni.internalToExternalPort[name] - if !ok || name == "" { - return - } - - sb := &ygnmi.SetBatch{} - sub := ni.getOrCreateInterface(modelName).GetOrCreateSubinterface(0) - - ip := au.LinkAddress.IP.String() - pl, _ := au.LinkAddress.Mask.Size() - isV4 := au.LinkAddress.IP.To4() != nil - log.V(1).Infof("handling addr update for %s ip %v pl %v", name, ip, pl) - if au.NewAddr { - var ipBytes []byte - if isV4 { - ipBytes = au.LinkAddress.IP.To4() - sub.GetOrCreateIpv4().GetOrCreateAddress(ip).PrefixLength = ygot.Uint8(uint8(pl)) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Address(ip).Ip().State(), au.LinkAddress.IP.String()) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Address(ip).PrefixLength().State(), uint8(pl)) - } else { - ipBytes = au.LinkAddress.IP.To16() - sub.GetOrCreateIpv6().GetOrCreateAddress(ip).PrefixLength = ygot.Uint8(uint8(pl)) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Address(ip).Ip().State(), au.LinkAddress.IP.String()) - gnmiclient.BatchUpdate(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Address(ip).PrefixLength().State(), uint8(pl)) - } - // Forward all packets destined to this interface to the corresponding TAP interface. - if err := ni.e.AddLayer3PuntRule(ctx, modelName, ipBytes); err != nil { - log.Warningf("failed to add layer3 punt rule: %v", err) - } - } else { - if isV4 { - sub.GetOrCreateIpv4().DeleteAddress(ip) - gnmiclient.BatchDelete(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Address(ip).State()) - } else { - sub.GetOrCreateIpv6().DeleteAddress(ip) - gnmiclient.BatchDelete(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Address(ip).State()) - } - } - if _, err := sb.Set(ctx, ni.c); err != nil { - log.Warningf("failed to set link status: %v", err) - } -} - -// handleNeighborUpdate modifies the state based on changes to the neighbor. -func (ni *Interface) handleNeighborUpdate(ctx context.Context, nu *netlink.NeighUpdate) { - ni.stateMu.Lock() - defer ni.stateMu.Unlock() - log.V(1).Infof("handling neighbor update for %s on %d", nu.IP.String(), nu.LinkIndex) - - name := ni.idxToName[nu.LinkIndex] - modelName, ok := ni.internalToExternalPort[name] - if name == "" || !ok { - return - } - - sb := &ygnmi.SetBatch{} - sub := ni.getOrCreateInterface(modelName).GetOrCreateSubinterface(0) - - switch nu.Type { - case unix.RTM_DELNEIGH: - req := &dpb.RemoveNeighborRequest{ - Dev: &dpb.RemoveNeighborRequest_PortId{ - PortId: ni.internalToExternalPort[ni.idxToName[nu.LinkIndex]], - }, - Ip: &dpb.RemoveNeighborRequest_IpBytes{ - IpBytes: ipToBytes(nu.IP), - }, - } - if _, err := ni.e.RemoveNeighbor(ctx, req); err != nil { - log.Warningf("failed to remove neighbor to dataplane: %v", err) - return - } - if nu.Family == unix.AF_INET6 { - sub.GetOrCreateIpv6().DeleteNeighbor(nu.IP.String()) - gnmiclient.BatchDelete(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Neighbor(nu.IP.String()).State()) - } else { - sub.GetOrCreateIpv4().DeleteNeighbor(nu.IP.String()) - gnmiclient.BatchDelete(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Neighbor(nu.IP.String()).State()) - } - case unix.RTM_NEWNEIGH: - if len(nu.HardwareAddr) == 0 { - log.Info("skipping neighbor update with no hwaddr") - return - } - req := &dpb.AddNeighborRequest{ - Dev: &dpb.AddNeighborRequest_PortId{ - PortId: ni.internalToExternalPort[ni.idxToName[nu.LinkIndex]], - }, - Mac: nu.HardwareAddr, - Ip: &dpb.AddNeighborRequest_IpBytes{ - IpBytes: ipToBytes(nu.IP), - }, - } - if _, err := ni.e.AddNeighbor(ctx, req); err != nil { - log.Warningf("failed to add neighbor to dataplane: %v", err) - return - } - if nu.Family == unix.AF_INET6 { - neigh := sub.GetOrCreateIpv6().GetOrCreateNeighbor(nu.IP.String()) - neigh.LinkLayerAddress = ygot.String(nu.HardwareAddr.String()) - if nu.Flags&unix.NUD_PERMANENT != 0 { - neigh.Origin = oc.IfIp_NeighborOrigin_STATIC - } else { - neigh.Origin = oc.IfIp_NeighborOrigin_DYNAMIC - } - gnmiclient.BatchReplace(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Neighbor(nu.IP.String()).Ip().State(), neigh.GetIp()) - gnmiclient.BatchReplace(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Neighbor(nu.IP.String()).LinkLayerAddress().State(), neigh.GetLinkLayerAddress()) - gnmiclient.BatchReplace(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv6().Neighbor(nu.IP.String()).Origin().State(), neigh.GetOrigin()) - } else { - neigh := sub.GetOrCreateIpv4().GetOrCreateNeighbor(nu.IP.String()) - neigh.LinkLayerAddress = ygot.String(nu.HardwareAddr.String()) - if nu.Flags&unix.NUD_PERMANENT != 0 { - neigh.Origin = oc.IfIp_NeighborOrigin_STATIC - } else { - neigh.Origin = oc.IfIp_NeighborOrigin_DYNAMIC - } - gnmiclient.BatchReplace(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Neighbor(nu.IP.String()).Ip().State(), neigh.GetIp()) - gnmiclient.BatchReplace(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Neighbor(nu.IP.String()).LinkLayerAddress().State(), neigh.GetLinkLayerAddress()) - gnmiclient.BatchReplace(sb, ocpath.Root().Interface(modelName).Subinterface(0).Ipv4().Neighbor(nu.IP.String()).Origin().State(), neigh.GetOrigin()) - } - default: - log.Warningf("unknown neigh update type: %v", nu.Type) - } - - if _, err := sb.Set(ctx, ni.c); err != nil { - log.Warningf("failed to set link status: %v", err) - } -} - -const ( - internalSuffix = "-internal" -) - -// setupPorts creates the dataplane ports and TAP interfaces for all interfaces on the device. -func (ni *Interface) setupPorts(ctx context.Context) error { - ifs, err := ni.ifaceMgr.GetAll() - if err != nil { - return err - } - for _, i := range ifs { - // Skip loopback, k8s pod interface, and tap interfaces. - if i.Name == "lo" || i.Name == "eth0" || strings.HasSuffix(i.Name, internalSuffix) { - continue - } - _, err = ni.e.CreatePort(ctx, &dpb.CreatePortRequest{ - Id: i.Name, - Type: fwdpb.PortType_PORT_TYPE_KERNEL, - Src: &dpb.CreatePortRequest_KernelDev{ - KernelDev: i.Name, - }, - Location: dpb.PortLocation_PORT_LOCATION_EXTERNAL, - }) - if err != nil { - return fmt.Errorf("failed to create kernel interface %q: %w", i.Name, err) - } - - ni.externalToInternalPort[i.Name] = i.Name + internalSuffix - ni.internalToExternalPort[i.Name+internalSuffix] = i.Name - - _, err := ni.e.CreatePort(ctx, &dpb.CreatePortRequest{ - Id: ni.externalToInternalPort[i.Name], - Type: fwdpb.PortType_PORT_TYPE_TAP, - Src: &dpb.CreatePortRequest_KernelDev{ - KernelDev: ni.externalToInternalPort[i.Name], - }, - ExternalPort: i.Name, - Location: dpb.PortLocation_PORT_LOCATION_INTERNAL, - }) - if err != nil { - return fmt.Errorf("failed to create tap interface %q: %w", ni.externalToInternalPort[i.Name], err) - } - - tap, err := ni.ifaceMgr.GetByName(ni.externalToInternalPort[i.Name]) - if err != nil { - return fmt.Errorf("failed to find tap interface %q: %w", ni.externalToInternalPort[i.Name], err) - } - ni.idxToName[i.Index] = i.Name - ni.idxToName[tap.Index] = tap.Name - - if err := ni.e.UpdatePortSrcMAC(ctx, i.Name, tap.HardwareAddr); err != nil { - return fmt.Errorf("failed to update MAC address for port %q: %w", i.Name, err) - } - ni.getOrCreateInterface(i.Name).GetOrCreateEthernet().SetHwMacAddress(tap.HardwareAddr.String()) - ni.getOrCreateInterface(i.Name).GetOrCreateEthernet().SetMacAddress(tap.HardwareAddr.String()) - if _, err := gnmiclient.Update(ctx, ni.c, ocpath.Root().Interface(i.Name).Ethernet().HwMacAddress().State(), tap.HardwareAddr.String()); err != nil { - return fmt.Errorf("failed to set hw addr of interface %q: %v", tap.Name, err) - } - if _, err := gnmiclient.Update(ctx, ni.c, ocpath.Root().Interface(i.Name).Ethernet().MacAddress().State(), tap.HardwareAddr.String()); err != nil { - return fmt.Errorf("failed to set hw addr of interface %q: %v", tap.Name, err) - } - } - return nil -} - -// ipToBytes converts a net.IP to a slice of bytes of the correct length (4 for IPv4, 16 for IPv6). -func ipToBytes(ip net.IP) []byte { - if ip.To4() != nil { - return ip.To4() - } - return ip.To16() -} diff --git a/dataplane/handlers/routes.go b/dataplane/handlers/routes.go deleted file mode 100644 index eb096c7d..00000000 --- a/dataplane/handlers/routes.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2022 Google LLC -// -// 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 handlers - -import ( - "context" - "fmt" - "strconv" - - "github.com/openconfig/ygnmi/schemaless" - "github.com/openconfig/ygnmi/ygnmi" - - "github.com/openconfig/lemming/dataplane/internal/engine" - "github.com/openconfig/lemming/gnmi" - "github.com/openconfig/lemming/gnmi/reconciler" - - log "github.com/golang/glog" - - dpb "github.com/openconfig/lemming/proto/dataplane" -) - -type route struct { - w *ygnmi.Watcher[*dpb.Route] - e *engine.Engine -} - -// RouteQuery returns a ygnmi query for a route with the given prefix and vrf. -func RouteQuery(vrf uint64, prefix string) ygnmi.ConfigQuery[*dpb.Route] { - q, err := schemaless.NewConfig[*dpb.Route](fmt.Sprintf("/dataplane/routes/route[prefix=%s][vrf=%d]", prefix, vrf), gnmi.InternalOrigin) - if err != nil { - log.Fatal(err) - } - return q -} - -var routesQuery ygnmi.WildcardQuery[*dpb.Route] - -// NewRoute returns a new route reconciler. -func NewRoute(e *engine.Engine) *reconciler.BuiltReconciler { - r := &route{ - e: e, - } - return reconciler.NewBuilder("dataplane-routes").WithStart(r.start).Build() -} - -func (r *route) start(ctx context.Context, client *ygnmi.Client) error { - r.w = ygnmi.WatchAll(ctx, client, routesQuery, func(v *ygnmi.Value[*dpb.Route]) error { - route, present := v.Val() - prefix := v.Path.Elem[2].Key["prefix"] - vrf, err := strconv.ParseUint(v.Path.Elem[2].Key["vrf"], 10, 64) - if err != nil { - log.Warningf("non-int vrf set in path: %v", err) - return ygnmi.Continue - } - - if !present { - if _, err := r.e.RemoveIPRoute(ctx, &dpb.RemoveIPRouteRequest{Prefix: &dpb.RoutePrefix{Prefix: &dpb.RoutePrefix_Cidr{Cidr: prefix}, VrfId: vrf}}); err != nil { - log.Warningf("failed to delete route: %v", err) - return ygnmi.Continue - } - return ygnmi.Continue - } - if len(route.GetNextHops().GetHops()) == 0 { - log.Warningf("no next hops for route insert or update") - return ygnmi.Continue - } - if _, err := r.e.AddIPRoute(ctx, &dpb.AddIPRouteRequest{Route: route}); err != nil { - log.Warningf("failed to add route: %v", err) - } - - return ygnmi.Continue - }) - return nil -} - -func init() { - q, err := schemaless.NewWildcard[*dpb.Route]("/dataplane/routes/route[prefix=*][vrf=*]", gnmi.InternalOrigin) - if err != nil { - log.Fatal(err) - } - routesQuery = q -} diff --git a/dataplane/internal/engine/BUILD b/dataplane/internal/engine/BUILD index 70eeeb0a..404c091e 100644 --- a/dataplane/internal/engine/BUILD +++ b/dataplane/internal/engine/BUILD @@ -10,13 +10,7 @@ go_library( visibility = ["//dataplane:__subpackages__"], deps = [ "//dataplane/forwarding", - "//dataplane/forwarding/attributes", - "//dataplane/forwarding/fwdconfig", "//dataplane/forwarding/infra/fwdcontext", - "//proto/dataplane", "//proto/forwarding", - "@com_github_golang_glog//:glog", - "@org_golang_google_grpc//codes", - "@org_golang_google_grpc//status", ], ) diff --git a/dataplane/internal/engine/engine.go b/dataplane/internal/engine/engine.go index 893f90e8..994f1554 100644 --- a/dataplane/internal/engine/engine.go +++ b/dataplane/internal/engine/engine.go @@ -16,24 +16,10 @@ package engine import ( "context" - "encoding/binary" - "fmt" - "net" - "net/netip" - "sync" - "sync/atomic" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "github.com/openconfig/lemming/dataplane/forwarding" - "github.com/openconfig/lemming/dataplane/forwarding/attributes" - "github.com/openconfig/lemming/dataplane/forwarding/fwdconfig" "github.com/openconfig/lemming/dataplane/forwarding/infra/fwdcontext" - log "github.com/golang/glog" - - dpb "github.com/openconfig/lemming/proto/dataplane" fwdpb "github.com/openconfig/lemming/proto/forwarding" ) @@ -51,48 +37,21 @@ const ( PreIngressActionTable = "preingress-table" IngressActionTable = "ingress-table" EgressActionTable = "egress-action-table" + NHActionTable = "nh-action" ) // Engine contains a routing context and methods to manage it. type Engine struct { - dpb.UnimplementedDataplaneServer *forwarding.Server - id string - idToNIDMu sync.RWMutex - // idToNID is map from RPC ID (proto), to internal object NID. - idToNID map[string]uint64 - nextNHGID atomic.Uint64 - nextNHID atomic.Uint64 - nextHopGroupsMu sync.Mutex - nextHopGroups map[uint64]*dpb.NextHopIDList - ifaceToPortMu sync.Mutex - // ifaceToPort is a map from interface id to port. For now, assume a 1:1 mapping. - // TODO: Clean up all the map and mutexes - ifaceToPort map[string]string - cpuPortID string - devNameToPortIDMu sync.Mutex - // devNameToPortID is a map from kernel device name to lucius port id. - devNameToPortID map[string]string - internalToExternalIDMu sync.Mutex - // internalToExternalID is a map from the internal port id to it's corresponding external port. - internalToExternalID map[string]string - cancelFn func() - createTables bool + id string + cancelFn func() } // New creates a new engine and sets up the forwarding tables. -// Disable table creating to use a custom forwarding pipeline. -// TODO: Delete this file. -func New(ctx context.Context, createTables bool) (*Engine, error) { +func New(ctx context.Context) (*Engine, error) { e := &Engine{ - id: "lucius", - Server: forwarding.New("engine"), - idToNID: map[string]uint64{}, - nextHopGroups: map[uint64]*dpb.NextHopIDList{}, - ifaceToPort: map[string]string{}, - devNameToPortID: map[string]string{}, - internalToExternalID: map[string]string{}, - createTables: createTables, + id: "lucius", + Server: forwarding.New("engine"), } ctx, e.cancelFn = context.WithCancel(ctx) @@ -103,12 +62,6 @@ func New(ctx context.Context, createTables bool) (*Engine, error) { if err != nil { return nil, err } - if createTables { - log.Info("setting up tables") - if err := e.setupTables(ctx); err != nil { - return nil, err - } - } return e, nil } @@ -122,14 +75,6 @@ func (e *Engine) Reset(ctx context.Context) error { return err } - e.idToNID = map[string]uint64{} - e.nextHopGroups = map[uint64]*dpb.NextHopIDList{} - e.ifaceToPort = map[string]string{} - e.devNameToPortID = map[string]string{} - e.internalToExternalID = map[string]string{} - e.nextNHGID.Store(0) - e.nextNHID.Store(0) - _, err = e.Server.ContextCreate(ctx, &fwdpb.ContextCreateRequest{ ContextId: &fwdpb.ContextId{Id: e.id}, }) @@ -137,12 +82,7 @@ func (e *Engine) Reset(ctx context.Context) error { return err } - ctx, e.cancelFn = context.WithCancel(ctx) - if e.createTables { - if err := e.setupTables(ctx); err != nil { - return err - } - } + _, e.cancelFn = context.WithCancel(ctx) return nil } @@ -151,1018 +91,7 @@ func (e *Engine) Context() (*fwdcontext.Context, error) { return e.Server.FindContext(&fwdpb.ContextId{Id: e.ID()}) } -func (e *Engine) setupTables(ctx context.Context) error { - v4FIB := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_PREFIX, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: FIBV4Table}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, - Table: &fwdpb.TableDesc_Prefix{ - Prefix: &fwdpb.PrefixTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_VRF, - }, - }, { - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, - }, - }}, - }, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, v4FIB); err != nil { - return err - } - v6FIB := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_PREFIX, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: FIBV6Table}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, - Table: &fwdpb.TableDesc_Prefix{ - Prefix: &fwdpb.PrefixTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_VRF, - }, - }, { - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, - }, - }}, - }, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, v6FIB); err != nil { - return err - } - portMAC := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_EXACT, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: SRCMACTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, - Table: &fwdpb.TableDesc_Exact{ - Exact: &fwdpb.ExactTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT, - }, - }}, - }, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, portMAC); err != nil { - return err - } - neighbor := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_EXACT, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: NeighborTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, - Table: &fwdpb.TableDesc_Exact{ - Exact: &fwdpb.ExactTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT, - }, - }, { - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP, - }, - }}, - }, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, neighbor); err != nil { - return err - } - nh := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_EXACT, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: NHTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, - Table: &fwdpb.TableDesc_Exact{ - Exact: &fwdpb.ExactTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID, - }, - }}, - }, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, nh); err != nil { - return err - } - nhg := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_EXACT, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: NHGTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, - Table: &fwdpb.TableDesc_Exact{ - Exact: &fwdpb.ExactTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID, - }, - }}, - }, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, nhg); err != nil { - return err - } - action := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_ACTION, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: PreIngressActionTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_CONTINUE}}, - Table: &fwdpb.TableDesc_Action{ - Action: &fwdpb.ActionTableDesc{}, - }, - }, - } - if _, err := e.Server.TableCreate(ctx, action); err != nil { - return err - } - action.Desc.TableId.ObjectId.Id = IngressActionTable - if _, err := e.Server.TableCreate(ctx, action); err != nil { - return err - } - action.Desc.TableId.ObjectId.Id = EgressActionTable - if _, err := e.Server.TableCreate(ctx, action); err != nil { - return err - } - - if err := CreateFIBSelector(ctx, e.id, e.Server); err != nil { - return err - } - if err := createLayer2PuntTable(ctx, e.id, e.Server); err != nil { - return err - } - return createLayer3PuntTable(ctx, e.id, e.Server) -} - // ID returns the engine's forwarding context id. func (e *Engine) ID() string { return e.id } - -func (e *Engine) CreatePort(ctx context.Context, req *dpb.CreatePortRequest) (*dpb.CreatePortResponse, error) { - var err error - switch req.Location { - case dpb.PortLocation_PORT_LOCATION_EXTERNAL: - err = e.CreateExternalPort(ctx, req.GetType(), req.GetId(), req.GetKernelDev()) - case dpb.PortLocation_PORT_LOCATION_INTERNAL: - err = e.CreateInternalPort(ctx, req.GetType(), req.GetId(), req.GetKernelDev(), req.GetExternalPort()) - case dpb.PortLocation_PORT_LOCATION_CPU: - e.cpuPortID = req.GetId() - req := &fwdpb.PortCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Port: &fwdpb.PortDesc{ - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: req.GetId()}}, - PortType: fwdpb.PortType_PORT_TYPE_CPU_PORT, - Port: &fwdpb.PortDesc_Cpu{ - Cpu: &fwdpb.CPUPortDesc{}, - }, - }, - } - _, err = e.PortCreate(ctx, req) - default: - return nil, fmt.Errorf("invalid port location: %v", req.Location) - } - return &dpb.CreatePortResponse{}, err -} - -// AddLayer3PuntRule adds rule to output packets to a corresponding port based on the destination IP and input port. -func (e *Engine) AddLayer3PuntRule(ctx context.Context, portID string, ip []byte) error { - e.idToNIDMu.Lock() - defer e.idToNIDMu.Unlock() - portNID := e.idToNID[portID] - - nidBytes := make([]byte, binary.Size(portNID)) - binary.BigEndian.PutUint64(nidBytes, portNID) - - log.Infof("adding layer3 punt rule: portID %s, id %d, ip %x", portID, portNID, ip) - - entries := &fwdpb.TableEntryAddRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - TableId: &fwdpb.TableId{ - ObjectId: &fwdpb.ObjectId{ - Id: layer3PuntTable, - }, - }, - Entries: []*fwdpb.TableEntryAddRequest_Entry{{ - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Exact{ - Exact: &fwdpb.ExactEntryDesc{ - Fields: []*fwdpb.PacketFieldBytes{{ - Bytes: nidBytes, - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT, - }, - }, - }, { - Bytes: ip, - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, - }, - }, - }}, - }, - }, - }, - Actions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_SWAP_OUTPUT_INTERNAL_EXTERNAL, - }, { - ActionType: fwdpb.ActionType_ACTION_TYPE_OUTPUT, - }}, - }}, - } - if _, err := e.Server.TableEntryAdd(ctx, entries); err != nil { - return err - } - return nil -} - -// prefixToPrimitives returns the primitive types of the route prefix. -// ip addr bytes, ip mask bytes, is ipv4, vrf id, error. -func prefixToPrimitives(prefix *dpb.RoutePrefix) ([]byte, []byte, bool, uint64, error) { - var ip []byte - var mask []byte - var isIPv4 bool - vrf := prefix.GetVrfId() - - switch pre := prefix.GetPrefix().(type) { - case *dpb.RoutePrefix_Cidr: - _, ipNet, err := net.ParseCIDR(pre.Cidr) - if err != nil { - return ip, mask, isIPv4, vrf, fmt.Errorf("failed to parse ip prefix: %v", err) - } - ip = ipNet.IP.To4() - mask = ipNet.Mask - isIPv4 = true - if ip == nil { - ip = ipNet.IP.To16() - mask = ipNet.Mask - isIPv4 = false - } - case *dpb.RoutePrefix_Mask: - ip = pre.Mask.Addr - mask = pre.Mask.Mask - switch len(ip) { - case net.IPv4len: - isIPv4 = true - case net.IPv6len: - isIPv4 = false - default: - return ip, mask, isIPv4, vrf, fmt.Errorf("invalid ip addr length: ip %v, mask %v", ip, mask) - } - default: - return ip, mask, isIPv4, vrf, fmt.Errorf("invalid prefix type") - } - return ip, mask, isIPv4, vrf, nil -} - -// addNextHopList creates all the next hops from the message, then create a next hop group if there are multiple next hops. -func (e *Engine) addNextHopList(ctx context.Context, nhg *dpb.NextHopList, mode dpb.GroupUpdateMode) ([]*fwdpb.ActionDesc, error) { - if len(nhg.GetHops()) == 1 { - nhID := e.nextNHID.Add(1) - if err := e.addNextHop(ctx, nhID, nhg.Hops[0]); err != nil { - return nil, err - } - return []*fwdpb.ActionDesc{ - fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID).WithUint64Value(nhID)).Build(), - fwdconfig.Action(fwdconfig.LookupAction(NHTable)).Build(), - }, nil - } - - idList := &dpb.NextHopIDList{} - for _, hop := range nhg.GetHops() { - nhID := e.nextNHID.Add(1) - if err := e.addNextHop(ctx, nhID, hop); err != nil { - return nil, err - } - idList.Hops = append(idList.Hops, nhID) - idList.Weights = append(idList.Weights, hop.Weight) - } - nhgID := e.nextNHGID.Add(1) - if err := e.addNextHopGroupIDList(ctx, nhgID, idList, mode); err != nil { - return nil, err - } - return []*fwdpb.ActionDesc{ - fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID).WithUint64Value(nhgID)).Build(), - fwdconfig.Action(fwdconfig.LookupAction(NHGTable)).Build(), - }, nil -} - -// addNextHopGroupIDList adds an entry to the next hop group table. -func (e *Engine) addNextHopGroupIDList(ctx context.Context, id uint64, nhg *dpb.NextHopIDList, mode dpb.GroupUpdateMode) error { - e.nextHopGroupsMu.Lock() - defer e.nextHopGroupsMu.Unlock() - - hops := nhg.GetHops() - weights := nhg.GetWeights() - if mode == dpb.GroupUpdateMode_GROUP_UPDATE_MODE_APPEND { - hops = append(e.nextHopGroups[id].Hops, nhg.GetHops()...) - weights = append(e.nextHopGroups[id].Weights, nhg.GetWeights()...) - } - - var actLists []*fwdpb.ActionList - for i, nh := range hops { - actLists = append(actLists, &fwdpb.ActionList{ - Weight: weights[i], - Actions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, - Action: &fwdpb.ActionDesc_Update{ - Update: &fwdpb.UpdateActionDesc{ - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID, - }, - }, - Type: fwdpb.UpdateType_UPDATE_TYPE_SET, - Value: binary.BigEndian.AppendUint64(nil, nh), - }, - }, - }}, - }) - } - // If there are multiple next-hops, configure the route to use ECMP or WCMP. - actions := []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_SELECT_ACTION_LIST, - Action: &fwdpb.ActionDesc_Select{ - Select: &fwdpb.SelectActionListActionDesc{ - SelectAlgorithm: fwdpb.SelectActionListActionDesc_SELECT_ALGORITHM_CRC32, // TODO: should algo + hash be configurable? - FieldIds: []*fwdpb.PacketFieldId{{Field: &fwdpb.PacketField{ // Hash the traffic flow, identified, IP protocol, L3 SRC, DST address, and L4 ports (if present). - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_PROTO, - }}, {Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_SRC, - }}, {Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, - }}, {Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L4_PORT_SRC, - }}, {Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L4_PORT_DST, - }}}, - ActionLists: actLists, - }, - }, - }, { - ActionType: fwdpb.ActionType_ACTION_TYPE_LOOKUP, - Action: &fwdpb.ActionDesc_Lookup{ - Lookup: &fwdpb.LookupActionDesc{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{ - Id: NHTable, - }}, - }, - }, - }} - - entries := &fwdpb.TableEntryAddRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - TableId: &fwdpb.TableId{ - ObjectId: &fwdpb.ObjectId{ - Id: NHGTable, - }, - }, - Entries: []*fwdpb.TableEntryAddRequest_Entry{{ - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Exact{ - Exact: &fwdpb.ExactEntryDesc{ - Fields: []*fwdpb.PacketFieldBytes{{ - Bytes: binary.BigEndian.AppendUint64(nil, id), - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID, - }, - }, - }}, - }, - }, - }, - Actions: actions, - }}, - } - - switch mode { - case dpb.GroupUpdateMode_GROUP_UPDATE_MODE_ERROR_ON_CONFLICT: - break - case dpb.GroupUpdateMode_GROUP_UPDATE_MODE_APPEND, dpb.GroupUpdateMode_GROUP_UPDATE_MODE_REPLACE: - if _, err := e.Server.TableEntryRemove(ctx, &fwdpb.TableEntryRemoveRequest{ - ContextId: entries.GetContextId(), - TableId: entries.GetTableId(), - Entries: []*fwdpb.EntryDesc{entries.GetEntries()[0].GetEntryDesc()}, - }); err != nil { - return err - } - default: - return fmt.Errorf("unknown mode: %v", mode) - } - - if _, err := e.Server.TableEntryAdd(ctx, entries); err != nil { - return err - } - e.nextHopGroups[id] = &dpb.NextHopIDList{ - Weights: weights, - Hops: hops, - } - - return nil -} - -// addNextHop adds an entry to the next hop table. -// TODO: Remove workaround that nexthop IP is not specified that the packet is treated as directly connected. -func (e *Engine) addNextHop(ctx context.Context, id uint64, nh *dpb.NextHop) error { - var nextHopIP []byte - if nhIPStr := nh.GetIpStr(); nhIPStr != "" { - nextHop := net.ParseIP(nhIPStr) - nextHopIP = nextHop.To4() - if nextHopIP == nil { - nextHopIP = nextHop.To16() - } - } else { - nextHopIP = nh.GetIpBytes() - } - // Set the next hop IP in the packet's metadata. - nextHopAct := fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithValue(nextHopIP)).Build() - if len(nextHopIP) == 0 { - nextHopAct = fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST)).Build() - } - var port string - // Set the output port of the packet. - switch dev := nh.GetDev().(type) { - case *dpb.NextHop_Port: - port = dev.Port - case *dpb.NextHop_Interface: - e.ifaceToPortMu.Lock() - port = e.ifaceToPort[dev.Interface] - e.ifaceToPortMu.Unlock() - default: - return fmt.Errorf("neither port nor interface specified") - } - transmitAct := fwdconfig.Action(fwdconfig.TransmitAction(port)).Build() - - acts := append([]*fwdpb.ActionDesc{nextHopAct, transmitAct}, nh.GetPreTransmitActions()...) - entries := &fwdpb.TableEntryAddRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - TableId: &fwdpb.TableId{ - ObjectId: &fwdpb.ObjectId{ - Id: NHTable, - }, - }, - Entries: []*fwdpb.TableEntryAddRequest_Entry{{ - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Exact{ - Exact: &fwdpb.ExactEntryDesc{ - Fields: []*fwdpb.PacketFieldBytes{{ - Bytes: binary.BigEndian.AppendUint64(nil, id), - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID, - }, - }, - }}, - }, - }, - }, - Actions: acts, - }}, - } - if _, err := e.Server.TableEntryAdd(ctx, entries); err != nil { - return err - } - - return nil -} - -func (e *Engine) actionsFromRoute(ctx context.Context, route *dpb.Route) ([]*fwdpb.ActionDesc, error) { - // If action is DROP, then skip handling next hops. - if route.GetAction() == dpb.PacketAction_PACKET_ACTION_DROP { - return []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_DROP}}, nil - } - - var actions []*fwdpb.ActionDesc - switch hop := route.GetHop().(type) { - case *dpb.Route_PortId: - actions = []*fwdpb.ActionDesc{ - // Set the next hop IP in the packet's metadata. - fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST)).Build(), - // Set the output port. - fwdconfig.Action(fwdconfig.TransmitAction(hop.PortId)).Build(), - } - case *dpb.Route_InterfaceId: - e.ifaceToPortMu.Lock() - port := e.ifaceToPort[hop.InterfaceId] - e.ifaceToPortMu.Unlock() - - actions = []*fwdpb.ActionDesc{ - // Set the next hop IP in the packet's metadata. - fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST)).Build(), - // Set the output port. - fwdconfig.Action(fwdconfig.TransmitAction(port)).Build(), - } - case *dpb.Route_NextHopId: - actions = []*fwdpb.ActionDesc{ // Set the next hop ID in the packet's metadata. - fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID).WithUint64Value(hop.NextHopId)).Build(), - fwdconfig.Action(fwdconfig.LookupAction(NHTable)).Build(), - } - case *dpb.Route_NextHopGroupId: - actions = []*fwdpb.ActionDesc{ // Set the next hop group ID in the packet's metadata. - fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID).WithUint64Value(hop.NextHopGroupId)).Build(), - fwdconfig.Action(fwdconfig.LookupAction(NHGTable)).Build(), - } - case *dpb.Route_NextHops: - var err error - actions, err = e.addNextHopList(ctx, hop.NextHops, dpb.GroupUpdateMode_GROUP_UPDATE_MODE_ERROR_ON_CONFLICT) - if err != nil { - return nil, err - } - } - return actions, nil -} - -// AddIPRoute adds a route to the FIB. It operates in two modes: -// 1. Client-managed IDs: each next hop and next hop group must be created before adding to a route with user provided ids. -// 2. Server-managed IDs: each next hop and next hop group must be specified with route. The server implicitly creates ids. -// TODO: Enforce that only one mode can be used. -func (e *Engine) AddIPRoute(ctx context.Context, req *dpb.AddIPRouteRequest) (*dpb.AddIPRouteResponse, error) { - ip, mask, isIPv4, vrf, err := prefixToPrimitives(req.GetRoute().GetPrefix()) - if err != nil { - return nil, err - } - fib := FIBV6Table - if isIPv4 { - fib = FIBV4Table - } - - entry := &fwdpb.TableEntryAddRequest{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: fib}}, - ContextId: &fwdpb.ContextId{Id: e.id}, - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Prefix{ - Prefix: &fwdpb.PrefixEntryDesc{ - Fields: []*fwdpb.PacketFieldMaskedBytes{{ - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_VRF}}, - Bytes: binary.BigEndian.AppendUint64(nil, vrf), - }, { - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST}}, - Bytes: ip, - Masks: mask, - }}, - }, - }, - }, - } - - entry.Actions, err = e.actionsFromRoute(ctx, req.GetRoute()) - if err != nil { - return nil, err - } - - if _, err := e.Server.TableEntryAdd(ctx, entry); err != nil { - return nil, err - } - - return &dpb.AddIPRouteResponse{}, nil -} - -// Remove deletes a route from the FIB. -// TODO: Clean up orphaned next-hop and next-hop-groups for server managed ids. -func (e *Engine) RemoveIPRoute(ctx context.Context, req *dpb.RemoveIPRouteRequest) (*dpb.RemoveIPRouteResponse, error) { - ip, mask, isIPv4, vrf, err := prefixToPrimitives(req.GetPrefix()) - if err != nil { - return nil, err - } - fib := FIBV6Table - if isIPv4 { - fib = FIBV4Table - } - entry := &fwdpb.TableEntryRemoveRequest{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: fib}}, - ContextId: &fwdpb.ContextId{Id: e.id}, - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Prefix{ - Prefix: &fwdpb.PrefixEntryDesc{ - Fields: []*fwdpb.PacketFieldMaskedBytes{{ - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_VRF}}, - Bytes: binary.BigEndian.AppendUint64(nil, vrf), - }, { - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST}}, - Bytes: ip, - Masks: mask, - }}, - }, - }, - }, - } - if _, err := e.Server.TableEntryRemove(ctx, entry); err != nil { - return nil, err - } - return &dpb.RemoveIPRouteResponse{}, nil -} - -// AddNext adds a next hop with a client-managed id. -func (e *Engine) AddNextHop(ctx context.Context, req *dpb.AddNextHopRequest) (*dpb.AddNextHopResponse, error) { - if err := e.addNextHop(ctx, req.GetId(), req.GetNextHop()); err != nil { - return nil, err - } - - return &dpb.AddNextHopResponse{}, nil -} - -// AddNext adds a next hop group with a client-managed id. -func (e *Engine) AddNextHopGroup(ctx context.Context, req *dpb.AddNextHopGroupRequest) (*dpb.AddNextHopGroupResponse, error) { - if err := e.addNextHopGroupIDList(ctx, req.GetId(), req.GetList(), req.GetMode()); err != nil { - return nil, err - } - - return &dpb.AddNextHopGroupResponse{}, nil -} - -type neighRequest interface { - GetIpBytes() []byte - GetIpStr() string - GetPortId() string - GetInterfaceId() string -} - -func (e *Engine) neighborReqToEntry(req neighRequest) (*fwdpb.EntryDesc, error) { - ip := req.GetIpBytes() - if len(ip) == 0 { - addr, err := netip.ParseAddr(req.GetIpStr()) - if err != nil { - return nil, err - } - ip = addr.AsSlice() - } - e.idToNIDMu.RLock() - defer e.idToNIDMu.RUnlock() - - port := req.GetPortId() - if port == "" { - e.ifaceToPortMu.Lock() - port = e.ifaceToPort[req.GetInterfaceId()] - e.ifaceToPortMu.Unlock() - } - if port == "" { - return nil, fmt.Errorf("neither port nor interface specified") - } - - idBytes := binary.BigEndian.AppendUint64([]byte{}, e.idToNID[port]) - - return &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Exact{ - Exact: &fwdpb.ExactEntryDesc{ - Fields: []*fwdpb.PacketFieldBytes{{ - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - Bytes: idBytes, - }, { - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - Bytes: ip, - }}, - }, - }, - }, nil -} - -// AddNeighbor adds a neighbor to the neighbor table. -func (e *Engine) AddNeighbor(ctx context.Context, req *dpb.AddNeighborRequest) (*dpb.AddNeighborResponse, error) { - entryDesc, err := e.neighborReqToEntry(req) - if err != nil { - return nil, err - } - - entry := &fwdpb.TableEntryAddRequest{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: NeighborTable}}, - ContextId: &fwdpb.ContextId{Id: e.id}, - EntryDesc: entryDesc, - Actions: []*fwdpb.ActionDesc{{ // Set the dst MAC. - ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, - Action: &fwdpb.ActionDesc_Update{ - Update: &fwdpb.UpdateActionDesc{ - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST, - }, - }, - Type: fwdpb.UpdateType_UPDATE_TYPE_SET, - Value: req.GetMac(), - }, - }, - }}, - } - if _, err := e.Server.TableEntryAdd(ctx, entry); err != nil { - return nil, err - } - log.V(1).Infof("added neighbor req: %v", req.String()) - - return &dpb.AddNeighborResponse{}, nil -} - -// RemoveNeighbor removes a neighbor from the neighbor table. -func (e *Engine) RemoveNeighbor(ctx context.Context, req *dpb.RemoveNeighborRequest) (*dpb.RemoveNeighborResponse, error) { - entryDesc, err := e.neighborReqToEntry(req) - if err != nil { - return nil, err - } - - entry := &fwdpb.TableEntryRemoveRequest{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: NeighborTable}}, - ContextId: &fwdpb.ContextId{Id: e.id}, - EntryDesc: entryDesc, - } - if _, err := e.Server.TableEntryRemove(ctx, entry); err != nil { - return nil, err - } - - return &dpb.RemoveNeighborResponse{}, nil -} - -// UpdatePortSrcMAC updates a port's source mac address. -func (e *Engine) UpdatePortSrcMAC(ctx context.Context, portID string, mac []byte) error { - e.idToNIDMu.RLock() - defer e.idToNIDMu.RUnlock() - idBytes := make([]byte, binary.Size(e.idToNID[portID])) - binary.BigEndian.PutUint64(idBytes, e.idToNID[portID]) - - entry := &fwdpb.TableEntryAddRequest{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: SRCMACTable}}, - ContextId: &fwdpb.ContextId{Id: e.id}, - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Exact{ - Exact: &fwdpb.ExactEntryDesc{ - Fields: []*fwdpb.PacketFieldBytes{{ - FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - Bytes: idBytes, - }}, - }, - }, - }, - Actions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, - Action: &fwdpb.ActionDesc_Update{ - Update: &fwdpb.UpdateActionDesc{ - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_SRC, - }, - }, - Type: fwdpb.UpdateType_UPDATE_TYPE_SET, - Value: mac, - }, - }, - }}, - } - if _, err := e.Server.TableEntryAdd(ctx, entry); err != nil { - return err - } - - return nil -} - -// CreateExternalPort creates an external port (connected to other devices). -func (e *Engine) CreateExternalPort(ctx context.Context, t fwdpb.PortType, id, devName string) error { - log.Infof("added external id %s, dev %s", id, devName) - nid, err := createPortAndEntries(ctx, e.id, e.Server, t, id, devName) - if err != nil { - return err - } - e.idToNIDMu.Lock() - e.idToNID[id] = nid - e.idToNIDMu.Unlock() - - update := &fwdpb.PortUpdateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: id}}, - Update: &fwdpb.PortUpdateDesc{ - Port: &fwdpb.PortUpdateDesc_Kernel{ - Kernel: &fwdpb.KernelPortUpdateDesc{ - Inputs: []*fwdpb.ActionDesc{ - fwdconfig.Action(fwdconfig.LookupAction(layer2PuntTable)).Build(), // Lookup in layer 2 table. - fwdconfig.Action(fwdconfig.LookupAction(layer3PuntTable)).Build(), // Lookup in layer 3 table. - fwdconfig.Action(fwdconfig.LookupAction(PreIngressActionTable)).Build(), - fwdconfig.Action(fwdconfig.DecapAction(fwdpb.PacketHeaderId_PACKET_HEADER_ID_ETHERNET)).Build(), // Decap L2 header. - fwdconfig.Action(fwdconfig.LookupAction(IngressActionTable)).Build(), - fwdconfig.Action(fwdconfig.LookupAction(FIBSelectorTable)).Build(), // Lookup in FIB. - fwdconfig.Action(fwdconfig.EncapAction(fwdpb.PacketHeaderId_PACKET_HEADER_ID_ETHERNET)).Build(), // Decap L2 header. - fwdconfig.Action(fwdconfig.LookupAction(NeighborTable)).Build(), // Lookup in the neighbor table. - fwdconfig.Action(fwdconfig.LookupAction(EgressActionTable)).Build(), - { - ActionType: fwdpb.ActionType_ACTION_TYPE_OUTPUT, - }, - }, - // update the src mac address with the configured port's mac address. - Outputs: []*fwdpb.ActionDesc{fwdconfig.Action(fwdconfig.LookupAction(SRCMACTable)).Build()}, - }, - }, - }, - } - if _, err := e.Server.PortUpdate(ctx, update); err != nil { - return err - } - return nil -} - -// CreateInternalPort creates an local (ie TAP) port for the given linux device name. -func (e *Engine) CreateInternalPort(ctx context.Context, t fwdpb.PortType, id, devName, externalID string) error { - log.Infof("added internal id %s, dev %s, external %s", id, devName, externalID) - nid, err := createPortAndEntries(ctx, e.id, e.Server, t, id, devName) - if err != nil { - return err - } - e.devNameToPortIDMu.Lock() - e.devNameToPortID[devName] = id - e.devNameToPortIDMu.Unlock() - - e.idToNIDMu.Lock() - e.idToNID[id] = nid - e.idToNIDMu.Unlock() - - e.internalToExternalIDMu.Lock() - e.internalToExternalID[id] = externalID - e.internalToExternalIDMu.Unlock() - - update := &fwdpb.PortUpdateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: id}}, - Update: &fwdpb.PortUpdateDesc{ - Port: &fwdpb.PortUpdateDesc_Kernel{ - Kernel: &fwdpb.KernelPortUpdateDesc{ - Inputs: []*fwdpb.ActionDesc{{ // Lookup in layer 2 table. - ActionType: fwdpb.ActionType_ACTION_TYPE_LOOKUP, - Action: &fwdpb.ActionDesc_Lookup{ - Lookup: &fwdpb.LookupActionDesc{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: layer2PuntTable}}, - }, - }, - }, { // Assume that the packet's originating from the device are sent to correct port. - ActionType: fwdpb.ActionType_ACTION_TYPE_SWAP_OUTPUT_INTERNAL_EXTERNAL, - }, { - ActionType: fwdpb.ActionType_ACTION_TYPE_OUTPUT, - }}, - }, - }, - }, - } - if _, err := e.Server.PortUpdate(ctx, update); err != nil { - return err - } - if externalID == "" { - return nil - } - _, err = e.Server.AttributeUpdate(ctx, &fwdpb.AttributeUpdateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - ObjectId: &fwdpb.ObjectId{Id: id}, - AttrId: attributes.SwapActionRelatedPort, - AttrValue: externalID, - }) - if err != nil { - return err - } - _, err = e.Server.AttributeUpdate(ctx, &fwdpb.AttributeUpdateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - ObjectId: &fwdpb.ObjectId{Id: externalID}, - AttrId: attributes.SwapActionRelatedPort, - AttrValue: id, - }) - if err != nil { - return err - } - - return nil -} - -// CreateLocalPort returns the counters for the object by name. -func (e *Engine) GetCounters(ctx context.Context, name string) (*fwdpb.ObjectCountersReply, error) { - return e.Server.ObjectCounters(ctx, &fwdpb.ObjectCountersRequest{ - ObjectId: &fwdpb.ObjectId{Id: name}, - ContextId: &fwdpb.ContextId{Id: e.id}, - }) -} - -// ModifyInterfacePorts adds and removes the ports from an aggregate interface. -func (e *Engine) ModifyInterfacePorts(ctx context.Context, portID string, addPortIDs, removePortIDs []string) error { - upds := []*fwdpb.PortUpdateDesc{} - for _, id := range addPortIDs { - upds = append(upds, &fwdpb.PortUpdateDesc{ - Port: &fwdpb.PortUpdateDesc_AggregateAdd{ - AggregateAdd: &fwdpb.AggregatePortAddMemberUpdateDesc{ - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: id}}, - }, - }, - }) - } - for _, id := range removePortIDs { - upds = append(upds, &fwdpb.PortUpdateDesc{ - Port: &fwdpb.PortUpdateDesc_AggregateDel{ - AggregateDel: &fwdpb.AggregatePortRemoveMemberUpdateDesc{ - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: id}}, - }, - }, - }) - } - for _, upd := range upds { - _, err := e.PortUpdate(ctx, &fwdpb.PortUpdateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: portID}}, - Update: upd, - }) - if err != nil { - return err - } - } - return nil -} - -// AddInterface adds an interface to the dataplane. -// TODO: Handle virtual router, mtu. -func (e *Engine) AddInterface(ctx context.Context, req *dpb.AddInterfaceRequest) (*dpb.AddInterfaceResponse, error) { - e.ifaceToPortMu.Lock() - defer e.ifaceToPortMu.Unlock() - - var portID string - switch req.GetType() { - case dpb.InterfaceType_INTERFACE_TYPE_AGGREGATE: - if nPorts := len(req.GetPortIds()); nPorts < 1 { - return nil, fmt.Errorf("invalid number of ports got %v, expected < 1", nPorts) - } - pcReq := &fwdpb.PortCreateRequest{ - ContextId: &fwdpb.ContextId{Id: e.id}, - Port: &fwdpb.PortDesc{ - PortType: fwdpb.PortType_PORT_TYPE_AGGREGATE_PORT, - }, - } - resp, err := e.PortCreate(ctx, pcReq) - if err != nil { - return nil, err - } - e.idToNIDMu.Lock() - e.idToNID[req.GetId()] = resp.ObjectIndex.GetIndex() - e.idToNIDMu.Unlock() - for _, member := range req.PortIds { - _, err := e.PortUpdate(ctx, &fwdpb.PortUpdateRequest{ - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: req.GetId()}}, - ContextId: &fwdpb.ContextId{Id: e.id}, - Update: &fwdpb.PortUpdateDesc{ - Port: &fwdpb.PortUpdateDesc_AggregateAdd{ - AggregateAdd: &fwdpb.AggregatePortAddMemberUpdateDesc{ - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: member}}, - }, - }, - }, - }) - if err != nil { - return nil, err - } - } - portID = req.GetId() - case dpb.InterfaceType_INTERFACE_TYPE_PORT: - if nPorts := len(req.GetPortIds()); nPorts != 1 { - return nil, fmt.Errorf("invalid number of ports got %v, expected 1", nPorts) - } - portID = req.GetPortIds()[0] - log.Infof("added interface id %s port id %s", req.GetId(), req.GetPortIds()[0]) - log.Infof("added port src mac %x", req.GetMac()) - e.ifaceToPort[req.GetId()] = req.GetPortIds()[0] - - case dpb.InterfaceType_INTERFACE_TYPE_LOOPBACK: // TODO: this may need to handled differently if multiple loopbacks are created. - portID := fmt.Sprintf("%s-port", req.GetId()) - if err := e.CreateExternalPort(ctx, fwdpb.PortType_PORT_TYPE_KERNEL, portID, "lo"); err != nil { - return nil, err - } - e.ifaceToPort[req.GetId()] = portID - return &dpb.AddInterfaceResponse{}, nil - default: - return nil, status.Errorf(codes.InvalidArgument, "interface type %T unrecongnized", req.GetType()) - } - - if err := e.UpdatePortSrcMAC(ctx, portID, req.GetMac()); err != nil { - return nil, err - } - - return &dpb.AddInterfaceResponse{}, nil -} - -// PortIDToNID returns the NID to for a given port id. -func (e *Engine) PortIDToNID(portID string) (uint64, bool) { - e.idToNIDMu.Lock() - defer e.idToNIDMu.Unlock() - nid, ok := e.idToNID[portID] - return nid, ok -} diff --git a/dataplane/internal/engine/helpers.go b/dataplane/internal/engine/helpers.go index 60a24157..d5017641 100644 --- a/dataplane/internal/engine/helpers.go +++ b/dataplane/internal/engine/helpers.go @@ -16,29 +16,10 @@ package engine import ( "context" - "encoding/binary" - "encoding/hex" fwdpb "github.com/openconfig/lemming/proto/forwarding" ) -var ( - etherBroadcast = mustParseHex("FFFFFFFFFFFF") - etherBroadcastMask = mustParseHex("FFFFFFFFFFFF") - etherMulticast = mustParseHex("0180C2000000") - etherMulticastMask = mustParseHex("FFFFFF000000") - etherIPV6Multi = mustParseHex("333300000000") - etherIPV6MultiMask = mustParseHex("FFFF00000000") -) - -func mustParseHex(hexStr string) []byte { - b, err := hex.DecodeString(hexStr) - if err != nil { - panic(err) - } - return b -} - type tableModifier interface { TableCreate(context.Context, *fwdpb.TableCreateRequest) (*fwdpb.TableCreateReply, error) TableEntryAdd(context.Context, *fwdpb.TableEntryAddRequest) (*fwdpb.TableEntryAddReply, error) @@ -120,207 +101,3 @@ func CreateFIBSelector(ctx context.Context, id string, c tableModifier) error { } return nil } - -// createLayer2PuntTable creates a table to packets to punt at layer 2 (input port and mac dst). -func createLayer2PuntTable(ctx context.Context, id string, c fwdpb.ForwardingServer) error { - arp := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_EXACT, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: arpPuntTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_CONTINUE}}, - Table: &fwdpb.TableDesc_Exact{ - Exact: &fwdpb.ExactTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_TYPE, - }, - }}, - }, - }, - }, - } - if _, err := c.TableCreate(ctx, arp); err != nil { - return err - } - entries := &fwdpb.TableEntryAddRequest{ - ContextId: &fwdpb.ContextId{Id: id}, - TableId: &fwdpb.TableId{ - ObjectId: &fwdpb.ObjectId{ - Id: arpPuntTable, - }, - }, - Entries: []*fwdpb.TableEntryAddRequest_Entry{{ - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Exact{ - Exact: &fwdpb.ExactEntryDesc{ - Fields: []*fwdpb.PacketFieldBytes{{ - Bytes: mustParseHex("0806"), - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_TYPE, - }, - }, - }}, - }, - }, - }, - Actions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_SWAP_OUTPUT_INTERNAL_EXTERNAL, - }, { - ActionType: fwdpb.ActionType_ACTION_TYPE_OUTPUT, - }}, - }}, - } - if _, err := c.TableEntryAdd(ctx, entries); err != nil { - return err - } - layer2 := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: id}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_PREFIX, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: layer2PuntTable}}, - Actions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_LOOKUP, - Action: &fwdpb.ActionDesc_Lookup{ - Lookup: &fwdpb.LookupActionDesc{ - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: arpPuntTable}}, - }, - }, - }}, - Table: &fwdpb.TableDesc_Prefix{ - Prefix: &fwdpb.PrefixTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT, - }, - }, { - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST, - }, - }}, - }, - }, - }, - } - if _, err := c.TableCreate(ctx, layer2); err != nil { - return err - } - return nil -} - -// addLayer2PuntRule adds rule to output packets to a corresponding port based on the destination MAC and input port. -func addLayer2PuntRule(ctx context.Context, ctxID string, c fwdpb.ForwardingServer, portNID uint64, mac, macMask []byte) error { - nidBytes := make([]byte, binary.Size(portNID)) - binary.BigEndian.PutUint64(nidBytes, portNID) - - entries := &fwdpb.TableEntryAddRequest{ - ContextId: &fwdpb.ContextId{Id: ctxID}, - TableId: &fwdpb.TableId{ - ObjectId: &fwdpb.ObjectId{ - Id: layer2PuntTable, - }, - }, - Entries: []*fwdpb.TableEntryAddRequest_Entry{{ - EntryDesc: &fwdpb.EntryDesc{ - Entry: &fwdpb.EntryDesc_Prefix{ - Prefix: &fwdpb.PrefixEntryDesc{ - Fields: []*fwdpb.PacketFieldMaskedBytes{{ - Bytes: nidBytes, - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT, - }, - }, - }, { - Bytes: mac, - Masks: macMask, - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST, - }, - }, - }}, - }, - }, - }, - Actions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_SWAP_OUTPUT_INTERNAL_EXTERNAL, - }, { - ActionType: fwdpb.ActionType_ACTION_TYPE_OUTPUT, - }}, - }}, - } - if _, err := c.TableEntryAdd(ctx, entries); err != nil { - return err - } - return nil -} - -// createLayer3PuntTable creates a table controlling whether packets to punt at layer 3 (input port and IP dst). -func createLayer3PuntTable(ctx context.Context, ctxID string, c fwdpb.ForwardingServer) error { - multicast := &fwdpb.TableCreateRequest{ - ContextId: &fwdpb.ContextId{Id: ctxID}, - Desc: &fwdpb.TableDesc{ - TableType: fwdpb.TableType_TABLE_TYPE_EXACT, - TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: layer3PuntTable}}, - Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_CONTINUE}}, - Table: &fwdpb.TableDesc_Exact{ - Exact: &fwdpb.ExactTableDesc{ - FieldIds: []*fwdpb.PacketFieldId{{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT, - }, - }, { - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, - }, - }}, - }, - }, - }, - } - if _, err := c.TableCreate(ctx, multicast); err != nil { - return err - } - return nil -} - -// createPortAndEntries creates a port and sets up the punt rules -func createPortAndEntries(ctx context.Context, ctxID string, c fwdpb.ForwardingServer, t fwdpb.PortType, id, devName string) (uint64, error) { - port := &fwdpb.PortCreateRequest{ - ContextId: &fwdpb.ContextId{Id: ctxID}, - Port: &fwdpb.PortDesc{ - PortType: t, - PortId: &fwdpb.PortId{ - ObjectId: &fwdpb.ObjectId{Id: id}, - }, - Port: &fwdpb.PortDesc_Kernel{ - Kernel: &fwdpb.KernelPortDesc{ - DeviceName: devName, - }, - }, - }, - } - if t == fwdpb.PortType_PORT_TYPE_TAP { - port.Port.Port = &fwdpb.PortDesc_Tap{ - Tap: &fwdpb.TAPPortDesc{ - DeviceName: devName, - }, - } - } - portID, err := c.PortCreate(ctx, port) - if err != nil { - return 0, err - } - if err := addLayer2PuntRule(ctx, ctxID, c, portID.GetObjectIndex().GetIndex(), etherBroadcast, etherBroadcastMask); err != nil { - return 0, err - } - if err := addLayer2PuntRule(ctx, ctxID, c, portID.GetObjectIndex().GetIndex(), etherMulticast, etherMulticastMask); err != nil { - return 0, err - } - if err := addLayer2PuntRule(ctx, ctxID, c, portID.GetObjectIndex().GetIndex(), etherIPV6Multi, etherIPV6MultiMask); err != nil { - return 0, err - } - return portID.GetObjectIndex().GetIndex(), nil -} diff --git a/dataplane/internal/kernel/kernel.go b/dataplane/internal/kernel/kernel.go index 8b40a78e..6cf2fe8d 100644 --- a/dataplane/internal/kernel/kernel.go +++ b/dataplane/internal/kernel/kernel.go @@ -20,6 +20,7 @@ package kernel import ( "fmt" "net" + "sort" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" @@ -117,7 +118,14 @@ func (k *Interfaces) CreateTAP(name string) (int, error) { // GetAll returns all interfaces. func (k *Interfaces) GetAll() ([]net.Interface, error) { - return net.Interfaces() + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + sort.Slice(ifaces, func(i, j int) bool { + return ifaces[i].Name < ifaces[j].Name + }) + return ifaces, nil } // GetByName returns all interfaces. diff --git a/dataplane/reconcilers_linux.go b/dataplane/reconcilers_linux.go index 6b78425b..66a5685d 100644 --- a/dataplane/reconcilers_linux.go +++ b/dataplane/reconcilers_linux.go @@ -18,11 +18,17 @@ package dataplane import ( - "github.com/openconfig/lemming/dataplane/handlers" - "github.com/openconfig/lemming/dataplane/internal/engine" + "google.golang.org/grpc" + + "github.com/openconfig/lemming/dataplane/dplanerc" "github.com/openconfig/lemming/gnmi/reconciler" ) -func getReconcilers(e *engine.Engine) []reconciler.Reconciler { - return []reconciler.Reconciler{handlers.NewInterface(e), handlers.NewRoute(e)} +func getReconcilers(conn grpc.ClientConnInterface, switchID uint64, cpuPortID uint64, contextID string) []reconciler.Reconciler { + r := dplanerc.New(conn, switchID, cpuPortID, contextID) + + return []reconciler.Reconciler{ + reconciler.NewBuilder("inferface").WithStart(r.StartInterface).Build(), + reconciler.NewBuilder("routes").WithStart(r.StartRoute).WithStop(r.Stop).Build(), + } } diff --git a/dataplane/reconcilers_nonlinux.go b/dataplane/reconcilers_nonlinux.go index eda1c7c9..2782cac7 100644 --- a/dataplane/reconcilers_nonlinux.go +++ b/dataplane/reconcilers_nonlinux.go @@ -18,11 +18,16 @@ package dataplane import ( - "github.com/openconfig/lemming/dataplane/handlers" - "github.com/openconfig/lemming/dataplane/internal/engine" + "google.golang.org/grpc" + + "github.com/openconfig/lemming/dataplane/dplanerc" "github.com/openconfig/lemming/gnmi/reconciler" ) -func getReconcilers(e *engine.Engine) []reconciler.Reconciler { - return []reconciler.Reconciler{handlers.NewRoute(e)} +func getReconcilers(conn grpc.ClientConnInterface, switchID uint64, cpuPortID uint64, contextID string) []reconciler.Reconciler { + r := dplanerc.New(conn, switchID, cpuPortID, contextID) + + return []reconciler.Reconciler{ + reconciler.NewBuilder("inferface").WithStart(r.StartInterface).Build(), + } } diff --git a/dataplane/server.go b/dataplane/server.go index edb85017..0cb9de00 100644 --- a/dataplane/server.go +++ b/dataplane/server.go @@ -24,22 +24,21 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/local" - "github.com/openconfig/lemming/dataplane/internal/engine" + "github.com/openconfig/lemming/dataplane/standalone/saiserver" + "github.com/openconfig/lemming/dataplane/standalone/saiserver/attrmgr" "github.com/openconfig/lemming/gnmi/oc" "github.com/openconfig/lemming/gnmi/reconciler" gpb "github.com/openconfig/gnmi/proto/gnmi" - dpb "github.com/openconfig/lemming/proto/dataplane" - fwdpb "github.com/openconfig/lemming/proto/forwarding" + saipb "github.com/openconfig/lemming/dataplane/standalone/proto" ) // Dataplane is an implementation of Dataplane HAL API. type Dataplane struct { - e *engine.Engine + saiserv *saiserver.Server srv *grpc.Server lis net.Listener - fwd fwdpb.ForwardingClient reconcilers []reconciler.Reconciler } @@ -47,21 +46,21 @@ type Dataplane struct { func New(ctx context.Context) (*Dataplane, error) { data := &Dataplane{} - e, err := engine.New(ctx, true) + lis, err := (&net.ListenConfig{}).Listen(ctx, "tcp", "127.0.0.1:0") if err != nil { - return nil, fmt.Errorf("failed to create engine: %w", err) + return nil, fmt.Errorf("failed to listen: %w", err) } - data.e = e - lis, err := net.Listen("tcp", "127.0.0.1:0") + mgr := attrmgr.New() + srv := grpc.NewServer(grpc.Creds(local.NewCredentials()), grpc.ChainUnaryInterceptor(mgr.Interceptor)) + + saiserv, err := saiserver.New(mgr, srv) if err != nil { - return nil, fmt.Errorf("failed to listen: %w", err) + return nil, fmt.Errorf("failed to create: %w", err) } - + data.saiserv = saiserv data.lis = lis - srv := grpc.NewServer(grpc.Creds(local.NewCredentials())) - fwdpb.RegisterForwardingServer(srv, data.e) - dpb.RegisterDataplaneServer(srv, data.e) + go srv.Serve(data.lis) return data, nil @@ -78,12 +77,45 @@ func (d *Dataplane) Start(ctx context.Context, c gpb.GNMIClient, target string) return fmt.Errorf("dataplane already started") } - fc, err := d.FwdClient() + conn, err := d.Conn() if err != nil { return err } - d.fwd = fc - d.reconcilers = append(d.reconcilers, getReconcilers(d.e)...) + sw := saipb.NewSwitchClient(conn) + hostif := saipb.NewHostifClient(conn) + swResp, err := sw.CreateSwitch(ctx, &saipb.CreateSwitchRequest{}) + if err != nil { + return err + } + swAttrs, err := sw.GetSwitchAttribute(ctx, &saipb.GetSwitchAttributeRequest{ + Oid: swResp.Oid, + AttrType: []saipb.SwitchAttr{ + saipb.SwitchAttr_SWITCH_ATTR_CPU_PORT, + }, + }) + if err != nil { + return err + } + + _, err = hostif.CreateHostifTrap(ctx, &saipb.CreateHostifTrapRequest{ + Switch: swResp.Oid, + TrapType: saipb.HostifTrapType_HOSTIF_TRAP_TYPE_ARP_REQUEST.Enum(), + PacketAction: saipb.PacketAction_PACKET_ACTION_TRAP.Enum(), + }) + if err != nil { + return err + } + _, err = hostif.CreateHostifTrap(ctx, &saipb.CreateHostifTrapRequest{ + Switch: swResp.Oid, + TrapType: saipb.HostifTrapType_HOSTIF_TRAP_TYPE_IPV6_NEIGHBOR_DISCOVERY.Enum(), + PacketAction: saipb.PacketAction_PACKET_ACTION_TRAP.Enum(), + }) + if err != nil { + return err + } + + // TODO: Completely remove engine and don't hardcode context ID. + d.reconcilers = append(d.reconcilers, getReconcilers(conn, swResp.Oid, *swAttrs.GetAttr().CpuPort, "lucius")...) for _, rec := range d.reconcilers { if err := rec.Start(ctx, c, target); err != nil { @@ -95,12 +127,12 @@ func (d *Dataplane) Start(ctx context.Context, c gpb.GNMIClient, target string) } // FwdClient gets a gRPC client to the packet forwarding engine. -func (d *Dataplane) FwdClient() (fwdpb.ForwardingClient, error) { +func (d *Dataplane) Conn() (grpc.ClientConnInterface, error) { conn, err := grpc.Dial(d.lis.Addr().String(), grpc.WithTransportCredentials(local.NewCredentials())) if err != nil { return nil, fmt.Errorf("failed to dial server: %w", err) } - return fwdpb.NewForwardingClient(conn), nil + return conn, nil } // Stop gracefully stops the server. diff --git a/dataplane/standalone/saiserver/BUILD b/dataplane/standalone/saiserver/BUILD index eec7af92..81454109 100644 --- a/dataplane/standalone/saiserver/BUILD +++ b/dataplane/standalone/saiserver/BUILD @@ -13,6 +13,7 @@ go_library( importpath = "github.com/openconfig/lemming/dataplane/standalone/saiserver", visibility = ["//visibility:public"], deps = [ + "//dataplane/config", "//dataplane/forwarding/attributes", "//dataplane/forwarding/fwdconfig", "//dataplane/forwarding/infra/fwdcontext", @@ -20,10 +21,10 @@ go_library( "//dataplane/standalone/packetio/cpusink", "//dataplane/standalone/proto:sai", "//dataplane/standalone/saiserver/attrmgr", - "//proto/dataplane", "//proto/forwarding", "@com_github_golang_glog//:glog", "@com_github_openconfig_gnmi//errlist", + "@com_github_spf13_viper//:viper", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//status", @@ -47,7 +48,6 @@ go_test( "//dataplane/internal/engine", "//dataplane/standalone/proto:sai", "//dataplane/standalone/saiserver/attrmgr", - "//proto/dataplane", "//proto/forwarding", "@com_github_google_go_cmp//cmp", "@com_github_openconfig_gnmi//errdiff", diff --git a/dataplane/standalone/saiserver/acl.go b/dataplane/standalone/saiserver/acl.go index 8c62af46..e38e8dce 100644 --- a/dataplane/standalone/saiserver/acl.go +++ b/dataplane/standalone/saiserver/acl.go @@ -152,13 +152,18 @@ func (a *acl) CreateAclEntry(ctx context.Context, req *saipb.CreateAclEntryReque }) } if req.GetFieldInPort() != nil { - nid, ok := a.dataplane.PortIDToNID(fmt.Sprint(req.FieldInPort.GetDataOid())) - if !ok { - return nil, fmt.Errorf("unknown port with id: %v", req.FieldInPort.GetDataOid()) + fwdCtx, err := a.dataplane.Context() + if err != nil { + return nil, err } + obj, err := fwdCtx.Objects.FindID(&fwdpb.ObjectId{Id: fmt.Sprint(req.FieldInPort.GetDataOid())}) + if err != nil { + return nil, err + } + nid := obj.NID() aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{ FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - Bytes: binary.BigEndian.AppendUint64(nil, nid), + Bytes: binary.BigEndian.AppendUint64(nil, uint64(nid)), Masks: binary.BigEndian.AppendUint64(nil, math.MaxUint64), }) } diff --git a/dataplane/standalone/saiserver/acl_test.go b/dataplane/standalone/saiserver/acl_test.go index 77a95b7c..21e3b4d0 100644 --- a/dataplane/standalone/saiserver/acl_test.go +++ b/dataplane/standalone/saiserver/acl_test.go @@ -27,6 +27,8 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + "github.com/openconfig/lemming/dataplane/forwarding/infra/fwdcontext" + "github.com/openconfig/lemming/dataplane/forwarding/infra/fwdobject" saipb "github.com/openconfig/lemming/dataplane/standalone/proto" "github.com/openconfig/lemming/dataplane/standalone/saiserver/attrmgr" fwdpb "github.com/openconfig/lemming/proto/forwarding" @@ -356,8 +358,9 @@ func TestCreateAclEntry(t *testing.T) { for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { dplane := &fakeSwitchDataplane{ - portIDToNID: map[string]uint64{"1": 1}, + ctx: fwdcontext.New("foo", "foo"), } + dplane.ctx.Objects.Insert(&fwdobject.Base{}, &fwdpb.ObjectId{Id: "1"}) c, a, stopFn := newTestACL(t, dplane) a.tableToLocation[1] = tableLocation{ groupID: "1", diff --git a/dataplane/standalone/saiserver/hostif.go b/dataplane/standalone/saiserver/hostif.go index 2ae48abb..b6e8ea6a 100644 --- a/dataplane/standalone/saiserver/hostif.go +++ b/dataplane/standalone/saiserver/hostif.go @@ -23,6 +23,9 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" + "github.com/spf13/viper" + + "github.com/openconfig/lemming/dataplane/config" "github.com/openconfig/lemming/dataplane/forwarding/attributes" "github.com/openconfig/lemming/dataplane/forwarding/fwdconfig" "github.com/openconfig/lemming/dataplane/standalone/saiserver/attrmgr" @@ -93,20 +96,33 @@ func (hostif *hostif) CreateHostif(ctx context.Context, req *saipb.CreateHostifR return &saipb.CreateHostifResponse{Oid: id}, nil case saipb.HostifType_HOSTIF_TYPE_NETDEV: + portType := fwdpb.PortType(fwdpb.PortType_value[viper.GetString(config.NetDevForwardingType)]) port := &fwdpb.PortCreateRequest{ ContextId: &fwdpb.ContextId{Id: hostif.dataplane.ID()}, Port: &fwdpb.PortDesc{ - PortType: fwdpb.PortType_PORT_TYPE_KERNEL, + PortType: portType, PortId: &fwdpb.PortId{ ObjectId: &fwdpb.ObjectId{Id: fmt.Sprint(id)}, }, - Port: &fwdpb.PortDesc_Kernel{ - Kernel: &fwdpb.KernelPortDesc{ - DeviceName: string(req.GetName()), - }, - }, }, } + switch portType { + case fwdpb.PortType_PORT_TYPE_KERNEL: + port.Port.Port = &fwdpb.PortDesc_Kernel{ + Kernel: &fwdpb.KernelPortDesc{ + DeviceName: string(req.GetName()), + }, + } + case fwdpb.PortType_PORT_TYPE_TAP: + port.Port.Port = &fwdpb.PortDesc_Tap{ + Tap: &fwdpb.TAPPortDesc{ + DeviceName: string(req.GetName()), + }, + } + default: + return nil, fmt.Errorf("unkown port type: %v", portType) + } + if _, err := hostif.dataplane.PortCreate(ctx, port); err != nil { if err != nil { return nil, err @@ -163,7 +179,7 @@ func (hostif *hostif) CreateHostif(ctx context.Context, req *saipb.CreateHostifR } hostif.mgr.StoreAttributes(id, attr) - // Notify the cpu sink about these port types. + // Notify the cpu sink about these port types, if there is one configured. fwdCtx, err := hostif.dataplane.Context() if err != nil { return nil, err @@ -171,19 +187,21 @@ func (hostif *hostif) CreateHostif(ctx context.Context, req *saipb.CreateHostifR fwdCtx.RLock() ps := fwdCtx.PacketSink() fwdCtx.RUnlock() - ps(&fwdpb.PacketSinkResponse{ - Resp: &fwdpb.PacketSinkResponse_Port{ - Port: &fwdpb.PacketSinkPortInfo{ - Port: &fwdpb.PortDesc{ - PortType: fwdpb.PortType_PORT_TYPE_KERNEL, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: fmt.Sprint(id)}}, - Port: &fwdpb.PortDesc_Kernel{ - Kernel: &fwdpb.KernelPortDesc{DeviceName: string(req.GetName())}, + if ps != nil { + ps(&fwdpb.PacketSinkResponse{ + Resp: &fwdpb.PacketSinkResponse_Port{ + Port: &fwdpb.PacketSinkPortInfo{ + Port: &fwdpb.PortDesc{ + PortType: fwdpb.PortType_PORT_TYPE_KERNEL, + PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: fmt.Sprint(id)}}, + Port: &fwdpb.PortDesc_Kernel{ + Kernel: &fwdpb.KernelPortDesc{DeviceName: string(req.GetName())}, + }, }, }, }, - }, - }) + }) + } default: return nil, status.Errorf(codes.InvalidArgument, "unknown type %v", req.GetType()) } diff --git a/dataplane/standalone/saiserver/routing.go b/dataplane/standalone/saiserver/routing.go index 4264a388..24a2e755 100644 --- a/dataplane/standalone/saiserver/routing.go +++ b/dataplane/standalone/saiserver/routing.go @@ -33,7 +33,6 @@ import ( log "github.com/golang/glog" saipb "github.com/openconfig/lemming/dataplane/standalone/proto" - dpb "github.com/openconfig/lemming/proto/dataplane" fwdpb "github.com/openconfig/lemming/proto/forwarding" ) @@ -56,7 +55,7 @@ func newNeighbor(mgr *attrmgr.AttrMgr, dataplane switchDataplaneAPI, s *grpc.Ser func (n *neighbor) CreateNeighborEntry(ctx context.Context, req *saipb.CreateNeighborEntryRequest) (*saipb.CreateNeighborEntryResponse, error) { entry := fwdconfig.TableEntryAddRequest(n.dataplane.ID(), engine.NeighborTable).AppendEntry(fwdconfig.EntryDesc(fwdconfig.ExactEntry( fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE).WithUint64(req.GetEntry().GetRifId()), - fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST).WithBytes(req.GetEntry().GetIpAddress()), + fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithBytes(req.GetEntry().GetIpAddress()), )), fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST).WithValue(req.GetDstMacAddress())), ).Build() @@ -66,6 +65,23 @@ func (n *neighbor) CreateNeighborEntry(ctx context.Context, req *saipb.CreateNei return &saipb.CreateNeighborEntryResponse{}, nil } +// CreateNeighborEntry adds a neighbor to the neighbor table. +func (n *neighbor) RemoveNeighborEntry(ctx context.Context, req *saipb.RemoveNeighborEntryRequest) (*saipb.RemoveNeighborEntryResponse, error) { + entry := fwdconfig.EntryDesc(fwdconfig.ExactEntry( + fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE).WithUint64(req.GetEntry().GetRifId()), + fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithBytes(req.GetEntry().GetIpAddress()), + )).Build() + + if _, err := n.dataplane.TableEntryRemove(ctx, &fwdpb.TableEntryRemoveRequest{ + ContextId: &fwdpb.ContextId{Id: n.dataplane.ID()}, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: engine.NeighborTable}}, + EntryDesc: entry, + }); err != nil { + return nil, err + } + return &saipb.RemoveNeighborEntryResponse{}, nil +} + // CreateNeighborEntries adds multiple neighbors to the neighbor table. func (n *neighbor) CreateNeighborEntries(ctx context.Context, re *saipb.CreateNeighborEntriesRequest) (*saipb.CreateNeighborEntriesResponse, error) { resp := &saipb.CreateNeighborEntriesResponse{} @@ -220,9 +236,10 @@ func (nh *nextHop) CreateNextHop(ctx context.Context, req *saipb.CreateNextHopRe } nhReq := fwdconfig.TableEntryAddRequest(nh.dataplane.ID(), engine.NHTable).AppendEntry( - fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID))), + fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID).WithUint64(id))), fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE).WithUint64Value(req.GetRouterInterfaceId())), fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithValue(req.GetIp())), + fwdconfig.Action(fwdconfig.LookupAction(engine.NHActionTable)), ) if _, err := nh.dataplane.TableEntryAdd(ctx, nhReq.Build()); err != nil { @@ -360,6 +377,28 @@ func (r *route) CreateRouteEntries(ctx context.Context, re *saipb.CreateRouteEnt return resp, errs.Err() } +func (r *route) RemoveRouteEntry(ctx context.Context, req *saipb.RemoveRouteEntryRequest) (*saipb.RemoveRouteEntryResponse, error) { + fib := engine.FIBV6Table + if len(req.GetEntry().GetDestination().GetAddr()) == 4 { + fib = engine.FIBV4Table + } + + _, err := r.dataplane.TableEntryRemove(ctx, &fwdpb.TableEntryRemoveRequest{ + ContextId: &fwdpb.ContextId{Id: r.dataplane.ID()}, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: fib}}, + EntryDesc: fwdconfig.EntryDesc( + fwdconfig.PrefixEntry( + fwdconfig.PacketFieldMaskedBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_VRF).WithUint64(req.GetEntry().GetVrId()), + fwdconfig.PacketFieldMaskedBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST).WithBytes( + req.GetEntry().GetDestination().GetAddr(), + req.GetEntry().GetDestination().GetMask(), + ), + ), + ).Build(), + }) + return &saipb.RemoveRouteEntryResponse{}, err +} + type routerInterface struct { saipb.UnimplementedRouterInterfaceServer mgr *attrmgr.AttrMgr @@ -378,17 +417,8 @@ func newRouterInterface(mgr *attrmgr.AttrMgr, dataplane switchDataplaneAPI, s *g // CreateRouterInterfaces creates a new router interface. func (ri *routerInterface) CreateRouterInterface(ctx context.Context, req *saipb.CreateRouterInterfaceRequest) (*saipb.CreateRouterInterfaceResponse, error) { id := ri.mgr.NextID() - iReq := &dpb.AddInterfaceRequest{ - Id: fmt.Sprint(id), - VrfId: uint32(req.GetVirtualRouterId()), - Mtu: uint64(req.GetMtu()), - PortIds: []string{fmt.Sprint(req.GetPortId())}, - Mac: req.GetSrcMacAddress(), - } switch req.GetType() { case saipb.RouterInterfaceType_ROUTER_INTERFACE_TYPE_PORT: - iReq.Type = dpb.InterfaceType_INTERFACE_TYPE_PORT - case saipb.RouterInterfaceType_ROUTER_INTERFACE_TYPE_LOOPBACK: // TODO: Support loopback interfaces log.Warning("loopback interfaces not supported") return &saipb.CreateRouterInterfaceResponse{Oid: id}, nil @@ -416,7 +446,7 @@ func (ri *routerInterface) CreateRouterInterface(ctx context.Context, req *saipb _, err = ri.dataplane.TableEntryAdd(ctx, fwdconfig.TableEntryAddRequest(ri.dataplane.ID(), outputIfaceTable). AppendEntry( - fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE).WithUint64(uint64(obj.NID())))), + fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE).WithUint64(id))), fwdconfig.Action(fwdconfig.TransmitAction(fmt.Sprint(req.GetPortId()))), ).Build()) if err != nil { diff --git a/dataplane/standalone/saiserver/routing_test.go b/dataplane/standalone/saiserver/routing_test.go index b0a4e081..18f180cb 100644 --- a/dataplane/standalone/saiserver/routing_test.go +++ b/dataplane/standalone/saiserver/routing_test.go @@ -273,11 +273,19 @@ func TestCreateNextHop(t *testing.T) { Value: []byte{0x7f, 0x00, 0x00, 0x01}, }, }, + }, { + ActionType: fwdpb.ActionType_ACTION_TYPE_LOOKUP, + Action: &fwdpb.ActionDesc_Lookup{ + Lookup: &fwdpb.LookupActionDesc{ + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: engine.NHActionTable}}, + }, + }, }}, EntryDesc: &fwdpb.EntryDesc{ Entry: &fwdpb.EntryDesc_Exact{ Exact: &fwdpb.ExactEntryDesc{ Fields: []*fwdpb.PacketFieldBytes{{ + Bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, FieldId: &fwdpb.PacketFieldId{ Field: &fwdpb.PacketField{ FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID, diff --git a/dataplane/standalone/saiserver/saiserver.go b/dataplane/standalone/saiserver/saiserver.go index 02b41e55..387cbd9b 100644 --- a/dataplane/standalone/saiserver/saiserver.go +++ b/dataplane/standalone/saiserver/saiserver.go @@ -26,7 +26,6 @@ import ( log "github.com/golang/glog" saipb "github.com/openconfig/lemming/dataplane/standalone/proto" - dpb "github.com/openconfig/lemming/proto/dataplane" fwdpb "github.com/openconfig/lemming/proto/forwarding" ) @@ -235,7 +234,7 @@ func (s *Server) Initialize(ctx context.Context, _ *saipb.InitializeRequest) (*s func New(mgr *attrmgr.AttrMgr, s *grpc.Server) (*Server, error) { ctx := context.Background() - e, err := engine.New(ctx, false) + e, err := engine.New(ctx) if err != nil { return nil, fmt.Errorf("failed create engine: %v", err) } @@ -278,7 +277,6 @@ func New(mgr *attrmgr.AttrMgr, s *grpc.Server) (*Server, error) { wred: &wred{}, } fwdpb.RegisterForwardingServer(s, e) - dpb.RegisterDataplaneServer(s, e) saipb.RegisterEntrypointServer(s, srv) saipb.RegisterBfdServer(s, srv.bfd) saipb.RegisterCounterServer(s, srv.counter) diff --git a/dataplane/standalone/saiserver/switch.go b/dataplane/standalone/saiserver/switch.go index dacf74be..75ab2672 100644 --- a/dataplane/standalone/saiserver/switch.go +++ b/dataplane/standalone/saiserver/switch.go @@ -57,7 +57,7 @@ type switchDataplaneAPI interface { NotifySubscribe(sub *fwdpb.NotifySubscribeRequest, srv fwdpb.Forwarding_NotifySubscribeServer) error TableCreate(context.Context, *fwdpb.TableCreateRequest) (*fwdpb.TableCreateReply, error) TableEntryAdd(context.Context, *fwdpb.TableEntryAddRequest) (*fwdpb.TableEntryAddReply, error) - PortIDToNID(port string) (uint64, bool) + TableEntryRemove(context.Context, *fwdpb.TableEntryRemoveRequest) (*fwdpb.TableEntryRemoveReply, error) ID() string PortState(ctx context.Context, req *fwdpb.PortStateRequest) (*fwdpb.PortStateReply, error) ObjectCounters(context.Context, *fwdpb.ObjectCountersRequest) (*fwdpb.ObjectCountersReply, error) @@ -280,6 +280,26 @@ func (sw *saiSwitch) CreateSwitch(ctx context.Context, _ *saipb.CreateSwitchRequ if _, err := sw.dataplane.TableCreate(ctx, action); err != nil { return nil, err } + nexthopAction := &fwdpb.TableCreateRequest{ + ContextId: &fwdpb.ContextId{Id: sw.dataplane.ID()}, + Desc: &fwdpb.TableDesc{ + TableType: fwdpb.TableType_TABLE_TYPE_EXACT, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: engine.NHActionTable}}, + Actions: []*fwdpb.ActionDesc{{ActionType: fwdpb.ActionType_ACTION_TYPE_CONTINUE}}, + Table: &fwdpb.TableDesc_Exact{ + Exact: &fwdpb.ExactTableDesc{ + FieldIds: []*fwdpb.PacketFieldId{{ + Field: &fwdpb.PacketField{ + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID, + }, + }}, + }, + }, + }, + } + if _, err := sw.dataplane.TableCreate(ctx, nexthopAction); err != nil { + return nil, err + } // Setup the packet io tables. A packet is punted by setting the output port to the CPU port. // There a two places where packets can be punted: diff --git a/dataplane/standalone/saiserver/switch_test.go b/dataplane/standalone/saiserver/switch_test.go index f7ae9b67..5958dc70 100644 --- a/dataplane/standalone/saiserver/switch_test.go +++ b/dataplane/standalone/saiserver/switch_test.go @@ -30,7 +30,6 @@ import ( "github.com/openconfig/lemming/dataplane/forwarding/infra/fwdcontext" "github.com/openconfig/lemming/dataplane/standalone/saiserver/attrmgr" - dpb "github.com/openconfig/lemming/proto/dataplane" fwdpb "github.com/openconfig/lemming/proto/forwarding" saipb "github.com/openconfig/lemming/dataplane/standalone/proto" @@ -215,7 +214,6 @@ type fakeSwitchDataplane struct { events []*fwdpb.EventDesc gotEntryAddReqs []*fwdpb.TableEntryAddRequest gotPortStateReq []*fwdpb.PortStateRequest - gotPortCreateReq []*dpb.CreatePortRequest counterReplies []*fwdpb.ObjectCountersReply portIDToNID map[string]uint64 counterRepliesIdx int @@ -238,16 +236,15 @@ func (f *fakeSwitchDataplane) TableEntryAdd(_ context.Context, req *fwdpb.TableE return nil, nil } +func (f *fakeSwitchDataplane) TableEntryRemove(context.Context, *fwdpb.TableEntryRemoveRequest) (*fwdpb.TableEntryRemoveReply, error) { + return nil, nil +} + func (f *fakeSwitchDataplane) PortIDToNID(id string) (uint64, bool) { nid, ok := f.portIDToNID[id] return nid, ok } -func (f *fakeSwitchDataplane) CreatePort(_ context.Context, req *dpb.CreatePortRequest) (*dpb.CreatePortResponse, error) { - f.gotPortCreateReq = append(f.gotPortCreateReq, req) - return nil, nil -} - func (f *fakeSwitchDataplane) PortState(_ context.Context, req *fwdpb.PortStateRequest) (*fwdpb.PortStateReply, error) { f.gotPortStateReq = append(f.gotPortStateReq, req) return nil, nil diff --git a/proto/dataplane/BUILD b/proto/dataplane/BUILD index a67ade2b..e14a07b9 100644 --- a/proto/dataplane/BUILD +++ b/proto/dataplane/BUILD @@ -7,16 +7,13 @@ proto_library( name = "dataplane_proto", srcs = ["dataplane.proto"], visibility = ["//visibility:public"], - deps = ["//proto/forwarding:forwarding_proto"], ) go_proto_library( name = "dataplane_go_proto", - compilers = ["@io_bazel_rules_go//proto:go_grpc"], importpath = "github.com/openconfig/lemming/proto/dataplane", proto = ":dataplane_proto", visibility = ["//visibility:public"], - deps = ["//proto/forwarding"], ) go_library( diff --git a/proto/dataplane/dataplane.pb.go b/proto/dataplane/dataplane.pb.go index 9f3f03ce..27c89d34 100644 --- a/proto/dataplane/dataplane.pb.go +++ b/proto/dataplane/dataplane.pb.go @@ -7,11 +7,6 @@ package dataplane import ( - context "context" - forwarding "github.com/openconfig/lemming/proto/forwarding" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -126,108 +121,130 @@ func (PacketAction) EnumDescriptor() ([]byte, []int) { return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{1} } -type GroupUpdateMode int32 +type OCInterface struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -const ( - GroupUpdateMode_GROUP_UPDATE_MODE_UNSPECIFIED GroupUpdateMode = 0 - GroupUpdateMode_GROUP_UPDATE_MODE_ERROR_ON_CONFLICT GroupUpdateMode = 1 - GroupUpdateMode_GROUP_UPDATE_MODE_APPEND GroupUpdateMode = 2 - GroupUpdateMode_GROUP_UPDATE_MODE_REPLACE GroupUpdateMode = 3 -) + Interface string `protobuf:"bytes,1,opt,name=interface,proto3" json:"interface,omitempty"` + Subinterface uint32 `protobuf:"varint,2,opt,name=subinterface,proto3" json:"subinterface,omitempty"` +} -// Enum value maps for GroupUpdateMode. -var ( - GroupUpdateMode_name = map[int32]string{ - 0: "GROUP_UPDATE_MODE_UNSPECIFIED", - 1: "GROUP_UPDATE_MODE_ERROR_ON_CONFLICT", - 2: "GROUP_UPDATE_MODE_APPEND", - 3: "GROUP_UPDATE_MODE_REPLACE", - } - GroupUpdateMode_value = map[string]int32{ - "GROUP_UPDATE_MODE_UNSPECIFIED": 0, - "GROUP_UPDATE_MODE_ERROR_ON_CONFLICT": 1, - "GROUP_UPDATE_MODE_APPEND": 2, - "GROUP_UPDATE_MODE_REPLACE": 3, +func (x *OCInterface) Reset() { + *x = OCInterface{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_dataplane_dataplane_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } -) - -func (x GroupUpdateMode) Enum() *GroupUpdateMode { - p := new(GroupUpdateMode) - *p = x - return p } -func (x GroupUpdateMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +func (x *OCInterface) String() string { + return protoimpl.X.MessageStringOf(x) } -func (GroupUpdateMode) Descriptor() protoreflect.EnumDescriptor { - return file_proto_dataplane_dataplane_proto_enumTypes[2].Descriptor() +func (*OCInterface) ProtoMessage() {} + +func (x *OCInterface) ProtoReflect() protoreflect.Message { + mi := &file_proto_dataplane_dataplane_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (GroupUpdateMode) Type() protoreflect.EnumType { - return &file_proto_dataplane_dataplane_proto_enumTypes[2] +// Deprecated: Use OCInterface.ProtoReflect.Descriptor instead. +func (*OCInterface) Descriptor() ([]byte, []int) { + return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{0} } -func (x GroupUpdateMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) +func (x *OCInterface) GetInterface() string { + if x != nil { + return x.Interface + } + return "" } -// Deprecated: Use GroupUpdateMode.Descriptor instead. -func (GroupUpdateMode) EnumDescriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{2} +func (x *OCInterface) GetSubinterface() uint32 { + if x != nil { + return x.Subinterface + } + return 0 } -type InterfaceType int32 +type GUE struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -const ( - InterfaceType_INTERFACE_TYPE_UNSPECIFIED InterfaceType = 0 - InterfaceType_INTERFACE_TYPE_PORT InterfaceType = 1 - InterfaceType_INTERFACE_TYPE_LOOPBACK InterfaceType = 2 - InterfaceType_INTERFACE_TYPE_AGGREGATE InterfaceType = 3 -) + SrcIp []byte `protobuf:"bytes,1,opt,name=src_ip,json=srcIp,proto3" json:"src_ip,omitempty"` + DstIp []byte `protobuf:"bytes,2,opt,name=dst_ip,json=dstIp,proto3" json:"dst_ip,omitempty"` + DstPort uint32 `protobuf:"varint,3,opt,name=dst_port,json=dstPort,proto3" json:"dst_port,omitempty"` + IsV6 bool `protobuf:"varint,4,opt,name=is_v6,json=isV6,proto3" json:"is_v6,omitempty"` +} -// Enum value maps for InterfaceType. -var ( - InterfaceType_name = map[int32]string{ - 0: "INTERFACE_TYPE_UNSPECIFIED", - 1: "INTERFACE_TYPE_PORT", - 2: "INTERFACE_TYPE_LOOPBACK", - 3: "INTERFACE_TYPE_AGGREGATE", - } - InterfaceType_value = map[string]int32{ - "INTERFACE_TYPE_UNSPECIFIED": 0, - "INTERFACE_TYPE_PORT": 1, - "INTERFACE_TYPE_LOOPBACK": 2, - "INTERFACE_TYPE_AGGREGATE": 3, +func (x *GUE) Reset() { + *x = GUE{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_dataplane_dataplane_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } -) +} -func (x InterfaceType) Enum() *InterfaceType { - p := new(InterfaceType) - *p = x - return p +func (x *GUE) String() string { + return protoimpl.X.MessageStringOf(x) } -func (x InterfaceType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +func (*GUE) ProtoMessage() {} + +func (x *GUE) ProtoReflect() protoreflect.Message { + mi := &file_proto_dataplane_dataplane_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (InterfaceType) Descriptor() protoreflect.EnumDescriptor { - return file_proto_dataplane_dataplane_proto_enumTypes[3].Descriptor() +// Deprecated: Use GUE.ProtoReflect.Descriptor instead. +func (*GUE) Descriptor() ([]byte, []int) { + return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{1} } -func (InterfaceType) Type() protoreflect.EnumType { - return &file_proto_dataplane_dataplane_proto_enumTypes[3] +func (x *GUE) GetSrcIp() []byte { + if x != nil { + return x.SrcIp + } + return nil } -func (x InterfaceType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) +func (x *GUE) GetDstIp() []byte { + if x != nil { + return x.DstIp + } + return nil } -// Deprecated: Use InterfaceType.Descriptor instead. -func (InterfaceType) EnumDescriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{3} +func (x *GUE) GetDstPort() uint32 { + if x != nil { + return x.DstPort + } + return 0 +} + +func (x *GUE) GetIsV6() bool { + if x != nil { + return x.IsV6 + } + return false } type NextHop struct { @@ -235,24 +252,18 @@ type NextHop struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Types that are assignable to Dev: + Interface *OCInterface `protobuf:"bytes,1,opt,name=interface,proto3" json:"interface,omitempty"` + NextHopIp string `protobuf:"bytes,2,opt,name=next_hop_ip,json=nextHopIp,proto3" json:"next_hop_ip,omitempty"` + // Types that are assignable to Encap: // - // *NextHop_Port - // *NextHop_Interface - Dev isNextHop_Dev `protobuf_oneof:"dev"` - // Types that are assignable to Ip: - // - // *NextHop_IpStr - // *NextHop_IpBytes - Ip isNextHop_Ip `protobuf_oneof:"ip"` - Weight uint64 `protobuf:"varint,5,opt,name=weight,proto3" json:"weight,omitempty"` - PreTransmitActions []*forwarding.ActionDesc `protobuf:"bytes,6,rep,name=pre_transmit_actions,json=preTransmitActions,proto3" json:"pre_transmit_actions,omitempty"` + // *NextHop_Gue + Encap isNextHop_Encap `protobuf_oneof:"encap"` } func (x *NextHop) Reset() { *x = NextHop{} if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[0] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -265,7 +276,7 @@ func (x *NextHop) String() string { func (*NextHop) ProtoMessage() {} func (x *NextHop) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[0] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -278,109 +289,60 @@ func (x *NextHop) ProtoReflect() protoreflect.Message { // Deprecated: Use NextHop.ProtoReflect.Descriptor instead. func (*NextHop) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{0} -} - -func (m *NextHop) GetDev() isNextHop_Dev { - if m != nil { - return m.Dev - } - return nil -} - -func (x *NextHop) GetPort() string { - if x, ok := x.GetDev().(*NextHop_Port); ok { - return x.Port - } - return "" + return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{2} } -func (x *NextHop) GetInterface() string { - if x, ok := x.GetDev().(*NextHop_Interface); ok { +func (x *NextHop) GetInterface() *OCInterface { + if x != nil { return x.Interface } - return "" -} - -func (m *NextHop) GetIp() isNextHop_Ip { - if m != nil { - return m.Ip - } return nil } -func (x *NextHop) GetIpStr() string { - if x, ok := x.GetIp().(*NextHop_IpStr); ok { - return x.IpStr +func (x *NextHop) GetNextHopIp() string { + if x != nil { + return x.NextHopIp } return "" } -func (x *NextHop) GetIpBytes() []byte { - if x, ok := x.GetIp().(*NextHop_IpBytes); ok { - return x.IpBytes +func (m *NextHop) GetEncap() isNextHop_Encap { + if m != nil { + return m.Encap } return nil } -func (x *NextHop) GetWeight() uint64 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *NextHop) GetPreTransmitActions() []*forwarding.ActionDesc { - if x != nil { - return x.PreTransmitActions +func (x *NextHop) GetGue() *GUE { + if x, ok := x.GetEncap().(*NextHop_Gue); ok { + return x.Gue } return nil } -type isNextHop_Dev interface { - isNextHop_Dev() +type isNextHop_Encap interface { + isNextHop_Encap() } -type NextHop_Port struct { - Port string `protobuf:"bytes,1,opt,name=port,proto3,oneof"` +type NextHop_Gue struct { + Gue *GUE `protobuf:"bytes,3,opt,name=gue,proto3,oneof"` } -type NextHop_Interface struct { - Interface string `protobuf:"bytes,2,opt,name=interface,proto3,oneof"` -} - -func (*NextHop_Port) isNextHop_Dev() {} - -func (*NextHop_Interface) isNextHop_Dev() {} - -type isNextHop_Ip interface { - isNextHop_Ip() -} - -type NextHop_IpStr struct { - IpStr string `protobuf:"bytes,3,opt,name=ip_str,json=ipStr,proto3,oneof"` -} - -type NextHop_IpBytes struct { - IpBytes []byte `protobuf:"bytes,4,opt,name=ip_bytes,json=ipBytes,proto3,oneof"` -} - -func (*NextHop_IpStr) isNextHop_Ip() {} - -func (*NextHop_IpBytes) isNextHop_Ip() {} +func (*NextHop_Gue) isNextHop_Encap() {} type NextHopList struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Hops []*NextHop `protobuf:"bytes,1,rep,name=hops,proto3" json:"hops,omitempty"` + Hops []*NextHop `protobuf:"bytes,1,rep,name=hops,proto3" json:"hops,omitempty"` + Weights []uint64 `protobuf:"varint,2,rep,packed,name=weights,proto3" json:"weights,omitempty"` } func (x *NextHopList) Reset() { *x = NextHopList{} if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[1] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -393,7 +355,7 @@ func (x *NextHopList) String() string { func (*NextHopList) ProtoMessage() {} func (x *NextHopList) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[1] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -406,7 +368,7 @@ func (x *NextHopList) ProtoReflect() protoreflect.Message { // Deprecated: Use NextHopList.ProtoReflect.Descriptor instead. func (*NextHopList) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{1} + return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{3} } func (x *NextHopList) GetHops() []*NextHop { @@ -416,55 +378,7 @@ func (x *NextHopList) GetHops() []*NextHop { return nil } -type NextHopIDList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Hops []uint64 `protobuf:"varint,1,rep,packed,name=hops,proto3" json:"hops,omitempty"` - Weights []uint64 `protobuf:"varint,2,rep,packed,name=weights,proto3" json:"weights,omitempty"` -} - -func (x *NextHopIDList) Reset() { - *x = NextHopIDList{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NextHopIDList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NextHopIDList) ProtoMessage() {} - -func (x *NextHopIDList) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NextHopIDList.ProtoReflect.Descriptor instead. -func (*NextHopIDList) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{2} -} - -func (x *NextHopIDList) GetHops() []uint64 { - if x != nil { - return x.Hops - } - return nil -} - -func (x *NextHopIDList) GetWeights() []uint64 { +func (x *NextHopList) GetWeights() []uint64 { if x != nil { return x.Weights } @@ -476,18 +390,14 @@ type RoutePrefix struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Types that are assignable to Prefix: - // - // *RoutePrefix_Cidr - // *RoutePrefix_Mask - Prefix isRoutePrefix_Prefix `protobuf_oneof:"prefix"` - VrfId uint64 `protobuf:"varint,3,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` + Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"` + NetworkInstance string `protobuf:"bytes,2,opt,name=network_instance,json=networkInstance,proto3" json:"network_instance,omitempty"` } func (x *RoutePrefix) Reset() { *x = RoutePrefix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[3] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -500,7 +410,7 @@ func (x *RoutePrefix) String() string { func (*RoutePrefix) ProtoMessage() {} func (x *RoutePrefix) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[3] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -513,53 +423,23 @@ func (x *RoutePrefix) ProtoReflect() protoreflect.Message { // Deprecated: Use RoutePrefix.ProtoReflect.Descriptor instead. func (*RoutePrefix) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{3} -} - -func (m *RoutePrefix) GetPrefix() isRoutePrefix_Prefix { - if m != nil { - return m.Prefix - } - return nil + return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{4} } func (x *RoutePrefix) GetCidr() string { - if x, ok := x.GetPrefix().(*RoutePrefix_Cidr); ok { + if x != nil { return x.Cidr } return "" } -func (x *RoutePrefix) GetMask() *IpMask { - if x, ok := x.GetPrefix().(*RoutePrefix_Mask); ok { - return x.Mask - } - return nil -} - -func (x *RoutePrefix) GetVrfId() uint64 { +func (x *RoutePrefix) GetNetworkInstance() string { if x != nil { - return x.VrfId + return x.NetworkInstance } - return 0 -} - -type isRoutePrefix_Prefix interface { - isRoutePrefix_Prefix() -} - -type RoutePrefix_Cidr struct { - Cidr string `protobuf:"bytes,1,opt,name=cidr,proto3,oneof"` -} - -type RoutePrefix_Mask struct { - Mask *IpMask `protobuf:"bytes,2,opt,name=mask,proto3,oneof"` + return "" } -func (*RoutePrefix_Cidr) isRoutePrefix_Prefix() {} - -func (*RoutePrefix_Mask) isRoutePrefix_Prefix() {} - type Route struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -569,18 +449,15 @@ type Route struct { Action PacketAction `protobuf:"varint,2,opt,name=action,proto3,enum=lemming.dataplane.PacketAction" json:"action,omitempty"` // Types that are assignable to Hop: // - // *Route_PortId - // *Route_NextHopId - // *Route_NextHopGroupId // *Route_NextHops - // *Route_InterfaceId + // *Route_Interface Hop isRoute_Hop `protobuf_oneof:"hop"` } func (x *Route) Reset() { *x = Route{} if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[4] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -593,7 +470,7 @@ func (x *Route) String() string { func (*Route) ProtoMessage() {} func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[4] + mi := &file_proto_dataplane_dataplane_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -606,7 +483,7 @@ func (x *Route) ProtoReflect() protoreflect.Message { // Deprecated: Use Route.ProtoReflect.Descriptor instead. func (*Route) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{4} + return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{5} } func (x *Route) GetPrefix() *RoutePrefix { @@ -630,27 +507,6 @@ func (m *Route) GetHop() isRoute_Hop { return nil } -func (x *Route) GetPortId() string { - if x, ok := x.GetHop().(*Route_PortId); ok { - return x.PortId - } - return "" -} - -func (x *Route) GetNextHopId() uint64 { - if x, ok := x.GetHop().(*Route_NextHopId); ok { - return x.NextHopId - } - return 0 -} - -func (x *Route) GetNextHopGroupId() uint64 { - if x, ok := x.GetHop().(*Route_NextHopGroupId); ok { - return x.NextHopGroupId - } - return 0 -} - func (x *Route) GetNextHops() *NextHopList { if x, ok := x.GetHop().(*Route_NextHops); ok { return x.NextHops @@ -658,1576 +514,150 @@ func (x *Route) GetNextHops() *NextHopList { return nil } -func (x *Route) GetInterfaceId() string { - if x, ok := x.GetHop().(*Route_InterfaceId); ok { - return x.InterfaceId +func (x *Route) GetInterface() *OCInterface { + if x, ok := x.GetHop().(*Route_Interface); ok { + return x.Interface } - return "" + return nil } type isRoute_Hop interface { isRoute_Hop() } -type Route_PortId struct { - PortId string `protobuf:"bytes,3,opt,name=port_id,json=portId,proto3,oneof"` -} - -type Route_NextHopId struct { - NextHopId uint64 `protobuf:"varint,4,opt,name=next_hop_id,json=nextHopId,proto3,oneof"` -} - -type Route_NextHopGroupId struct { - NextHopGroupId uint64 `protobuf:"varint,5,opt,name=next_hop_group_id,json=nextHopGroupId,proto3,oneof"` -} - type Route_NextHops struct { - NextHops *NextHopList `protobuf:"bytes,6,opt,name=next_hops,json=nextHops,proto3,oneof"` + NextHops *NextHopList `protobuf:"bytes,3,opt,name=next_hops,json=nextHops,proto3,oneof"` } -type Route_InterfaceId struct { - InterfaceId string `protobuf:"bytes,7,opt,name=interface_id,json=interfaceId,proto3,oneof"` +type Route_Interface struct { + Interface *OCInterface `protobuf:"bytes,4,opt,name=interface,proto3,oneof"` } -func (*Route_PortId) isRoute_Hop() {} - -func (*Route_NextHopId) isRoute_Hop() {} - -func (*Route_NextHopGroupId) isRoute_Hop() {} - func (*Route_NextHops) isRoute_Hop() {} -func (*Route_InterfaceId) isRoute_Hop() {} +func (*Route_Interface) isRoute_Hop() {} -type CreatePortRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +var File_proto_dataplane_dataplane_proto protoreflect.FileDescriptor - Type forwarding.PortType `protobuf:"varint,1,opt,name=type,proto3,enum=forwarding.PortType" json:"type,omitempty"` - Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` - // Types that are assignable to Src: - // - // *CreatePortRequest_KernelDev - Src isCreatePortRequest_Src `protobuf_oneof:"src"` - ExternalPort string `protobuf:"bytes,4,opt,name=external_port,json=externalPort,proto3" json:"external_port,omitempty"` - Location PortLocation `protobuf:"varint,5,opt,name=location,proto3,enum=lemming.dataplane.PortLocation" json:"location,omitempty"` +var file_proto_dataplane_dataplane_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x11, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x22, 0x4f, 0x0a, 0x0b, 0x4f, 0x43, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x63, 0x0a, 0x03, 0x47, 0x55, 0x45, 0x12, 0x15, 0x0a, 0x06, + 0x73, 0x72, 0x63, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x72, + 0x63, 0x49, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, + 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, + 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x76, 0x36, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x56, 0x36, 0x22, 0x9c, 0x01, 0x0a, 0x07, 0x4e, + 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x12, 0x3c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, + 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x4f, 0x43, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, + 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x48, + 0x6f, 0x70, 0x49, 0x70, 0x12, 0x2a, 0x0a, 0x03, 0x67, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x55, 0x45, 0x48, 0x00, 0x52, 0x03, 0x67, 0x75, 0x65, + 0x42, 0x07, 0x0a, 0x05, 0x65, 0x6e, 0x63, 0x61, 0x70, 0x22, 0x57, 0x0a, 0x0b, 0x4e, 0x65, 0x78, + 0x74, 0x48, 0x6f, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x68, 0x6f, 0x70, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, + 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x48, + 0x6f, 0x70, 0x52, 0x04, 0x68, 0x6f, 0x70, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x22, 0x4c, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x22, 0xfe, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x65, 0x6d, + 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, + 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x09, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, + 0x52, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x4f, 0x43, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x48, 0x00, 0x52, + 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x68, 0x6f, + 0x70, 0x2a, 0x7c, 0x0a, 0x0c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, + 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x58, + 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x4f, 0x52, 0x54, + 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x50, 0x55, 0x10, 0x03, 0x2a, + 0x60, 0x0a, 0x0c, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1d, 0x0a, 0x19, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, + 0x0a, 0x12, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, + 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x10, + 0x02, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6c, 0x65, 0x6d, 0x6d, 0x69, + 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } -func (x *CreatePortRequest) Reset() { - *x = CreatePortRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} +var ( + file_proto_dataplane_dataplane_proto_rawDescOnce sync.Once + file_proto_dataplane_dataplane_proto_rawDescData = file_proto_dataplane_dataplane_proto_rawDesc +) -func (x *CreatePortRequest) String() string { - return protoimpl.X.MessageStringOf(x) +func file_proto_dataplane_dataplane_proto_rawDescGZIP() []byte { + file_proto_dataplane_dataplane_proto_rawDescOnce.Do(func() { + file_proto_dataplane_dataplane_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_dataplane_dataplane_proto_rawDescData) + }) + return file_proto_dataplane_dataplane_proto_rawDescData } -func (*CreatePortRequest) ProtoMessage() {} +var file_proto_dataplane_dataplane_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_proto_dataplane_dataplane_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_proto_dataplane_dataplane_proto_goTypes = []interface{}{ + (PortLocation)(0), // 0: lemming.dataplane.PortLocation + (PacketAction)(0), // 1: lemming.dataplane.PacketAction + (*OCInterface)(nil), // 2: lemming.dataplane.OCInterface + (*GUE)(nil), // 3: lemming.dataplane.GUE + (*NextHop)(nil), // 4: lemming.dataplane.NextHop + (*NextHopList)(nil), // 5: lemming.dataplane.NextHopList + (*RoutePrefix)(nil), // 6: lemming.dataplane.RoutePrefix + (*Route)(nil), // 7: lemming.dataplane.Route +} +var file_proto_dataplane_dataplane_proto_depIdxs = []int32{ + 2, // 0: lemming.dataplane.NextHop.interface:type_name -> lemming.dataplane.OCInterface + 3, // 1: lemming.dataplane.NextHop.gue:type_name -> lemming.dataplane.GUE + 4, // 2: lemming.dataplane.NextHopList.hops:type_name -> lemming.dataplane.NextHop + 6, // 3: lemming.dataplane.Route.prefix:type_name -> lemming.dataplane.RoutePrefix + 1, // 4: lemming.dataplane.Route.action:type_name -> lemming.dataplane.PacketAction + 5, // 5: lemming.dataplane.Route.next_hops:type_name -> lemming.dataplane.NextHopList + 2, // 6: lemming.dataplane.Route.interface:type_name -> lemming.dataplane.OCInterface + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} -func (x *CreatePortRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreatePortRequest.ProtoReflect.Descriptor instead. -func (*CreatePortRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{5} -} - -func (x *CreatePortRequest) GetType() forwarding.PortType { - if x != nil { - return x.Type - } - return forwarding.PortType(0) -} - -func (x *CreatePortRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (m *CreatePortRequest) GetSrc() isCreatePortRequest_Src { - if m != nil { - return m.Src - } - return nil -} - -func (x *CreatePortRequest) GetKernelDev() string { - if x, ok := x.GetSrc().(*CreatePortRequest_KernelDev); ok { - return x.KernelDev - } - return "" -} - -func (x *CreatePortRequest) GetExternalPort() string { - if x != nil { - return x.ExternalPort - } - return "" -} - -func (x *CreatePortRequest) GetLocation() PortLocation { - if x != nil { - return x.Location - } - return PortLocation_PORT_LOCATION_UNSPECIFIED -} - -type isCreatePortRequest_Src interface { - isCreatePortRequest_Src() -} - -type CreatePortRequest_KernelDev struct { - KernelDev string `protobuf:"bytes,3,opt,name=kernel_dev,json=kernelDev,proto3,oneof"` -} - -func (*CreatePortRequest_KernelDev) isCreatePortRequest_Src() {} - -type CreatePortResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *CreatePortResponse) Reset() { - *x = CreatePortResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreatePortResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreatePortResponse) ProtoMessage() {} - -func (x *CreatePortResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreatePortResponse.ProtoReflect.Descriptor instead. -func (*CreatePortResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{6} -} - -type IpMask struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Addr []byte `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` - Mask []byte `protobuf:"bytes,2,opt,name=mask,proto3" json:"mask,omitempty"` -} - -func (x *IpMask) Reset() { - *x = IpMask{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IpMask) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IpMask) ProtoMessage() {} - -func (x *IpMask) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IpMask.ProtoReflect.Descriptor instead. -func (*IpMask) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{7} -} - -func (x *IpMask) GetAddr() []byte { - if x != nil { - return x.Addr - } - return nil -} - -func (x *IpMask) GetMask() []byte { - if x != nil { - return x.Mask - } - return nil -} - -type AddIPRouteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Route *Route `protobuf:"bytes,1,opt,name=route,proto3" json:"route,omitempty"` -} - -func (x *AddIPRouteRequest) Reset() { - *x = AddIPRouteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddIPRouteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddIPRouteRequest) ProtoMessage() {} - -func (x *AddIPRouteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddIPRouteRequest.ProtoReflect.Descriptor instead. -func (*AddIPRouteRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{8} -} - -func (x *AddIPRouteRequest) GetRoute() *Route { - if x != nil { - return x.Route - } - return nil -} - -type AddIPRouteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AddIPRouteResponse) Reset() { - *x = AddIPRouteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddIPRouteResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddIPRouteResponse) ProtoMessage() {} - -func (x *AddIPRouteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddIPRouteResponse.ProtoReflect.Descriptor instead. -func (*AddIPRouteResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{9} -} - -type RemoveIPRouteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Prefix *RoutePrefix `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` -} - -func (x *RemoveIPRouteRequest) Reset() { - *x = RemoveIPRouteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveIPRouteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveIPRouteRequest) ProtoMessage() {} - -func (x *RemoveIPRouteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveIPRouteRequest.ProtoReflect.Descriptor instead. -func (*RemoveIPRouteRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{10} -} - -func (x *RemoveIPRouteRequest) GetPrefix() *RoutePrefix { - if x != nil { - return x.Prefix - } - return nil -} - -type RemoveIPRouteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RemoveIPRouteResponse) Reset() { - *x = RemoveIPRouteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveIPRouteResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveIPRouteResponse) ProtoMessage() {} - -func (x *RemoveIPRouteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveIPRouteResponse.ProtoReflect.Descriptor instead. -func (*RemoveIPRouteResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{11} -} - -type AddNextHopRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - NextHop *NextHop `protobuf:"bytes,2,opt,name=next_hop,json=nextHop,proto3" json:"next_hop,omitempty"` -} - -func (x *AddNextHopRequest) Reset() { - *x = AddNextHopRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddNextHopRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddNextHopRequest) ProtoMessage() {} - -func (x *AddNextHopRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddNextHopRequest.ProtoReflect.Descriptor instead. -func (*AddNextHopRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{12} -} - -func (x *AddNextHopRequest) GetId() uint64 { - if x != nil { - return x.Id - } - return 0 -} - -func (x *AddNextHopRequest) GetNextHop() *NextHop { - if x != nil { - return x.NextHop - } - return nil -} - -type AddNextHopResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AddNextHopResponse) Reset() { - *x = AddNextHopResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddNextHopResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddNextHopResponse) ProtoMessage() {} - -func (x *AddNextHopResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddNextHopResponse.ProtoReflect.Descriptor instead. -func (*AddNextHopResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{13} -} - -type AddNextHopGroupRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - List *NextHopIDList `protobuf:"bytes,2,opt,name=list,proto3" json:"list,omitempty"` - Mode GroupUpdateMode `protobuf:"varint,3,opt,name=mode,proto3,enum=lemming.dataplane.GroupUpdateMode" json:"mode,omitempty"` -} - -func (x *AddNextHopGroupRequest) Reset() { - *x = AddNextHopGroupRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddNextHopGroupRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddNextHopGroupRequest) ProtoMessage() {} - -func (x *AddNextHopGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddNextHopGroupRequest.ProtoReflect.Descriptor instead. -func (*AddNextHopGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{14} -} - -func (x *AddNextHopGroupRequest) GetId() uint64 { - if x != nil { - return x.Id - } - return 0 -} - -func (x *AddNextHopGroupRequest) GetList() *NextHopIDList { - if x != nil { - return x.List - } - return nil -} - -func (x *AddNextHopGroupRequest) GetMode() GroupUpdateMode { - if x != nil { - return x.Mode - } - return GroupUpdateMode_GROUP_UPDATE_MODE_UNSPECIFIED -} - -type AddNextHopGroupResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AddNextHopGroupResponse) Reset() { - *x = AddNextHopGroupResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddNextHopGroupResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddNextHopGroupResponse) ProtoMessage() {} - -func (x *AddNextHopGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddNextHopGroupResponse.ProtoReflect.Descriptor instead. -func (*AddNextHopGroupResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{15} -} - -type AddNeighborRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Dev: - // - // *AddNeighborRequest_PortId - // *AddNeighborRequest_InterfaceId - Dev isAddNeighborRequest_Dev `protobuf_oneof:"dev"` - // Types that are assignable to Ip: - // - // *AddNeighborRequest_IpStr - // *AddNeighborRequest_IpBytes - Ip isAddNeighborRequest_Ip `protobuf_oneof:"ip"` - Mac []byte `protobuf:"bytes,4,opt,name=mac,proto3" json:"mac,omitempty"` -} - -func (x *AddNeighborRequest) Reset() { - *x = AddNeighborRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddNeighborRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddNeighborRequest) ProtoMessage() {} - -func (x *AddNeighborRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddNeighborRequest.ProtoReflect.Descriptor instead. -func (*AddNeighborRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{16} -} - -func (m *AddNeighborRequest) GetDev() isAddNeighborRequest_Dev { - if m != nil { - return m.Dev - } - return nil -} - -func (x *AddNeighborRequest) GetPortId() string { - if x, ok := x.GetDev().(*AddNeighborRequest_PortId); ok { - return x.PortId - } - return "" -} - -func (x *AddNeighborRequest) GetInterfaceId() string { - if x, ok := x.GetDev().(*AddNeighborRequest_InterfaceId); ok { - return x.InterfaceId - } - return "" -} - -func (m *AddNeighborRequest) GetIp() isAddNeighborRequest_Ip { - if m != nil { - return m.Ip - } - return nil -} - -func (x *AddNeighborRequest) GetIpStr() string { - if x, ok := x.GetIp().(*AddNeighborRequest_IpStr); ok { - return x.IpStr - } - return "" -} - -func (x *AddNeighborRequest) GetIpBytes() []byte { - if x, ok := x.GetIp().(*AddNeighborRequest_IpBytes); ok { - return x.IpBytes - } - return nil -} - -func (x *AddNeighborRequest) GetMac() []byte { - if x != nil { - return x.Mac - } - return nil -} - -type isAddNeighborRequest_Dev interface { - isAddNeighborRequest_Dev() -} - -type AddNeighborRequest_PortId struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3,oneof"` -} - -type AddNeighborRequest_InterfaceId struct { - InterfaceId string `protobuf:"bytes,5,opt,name=interface_id,json=interfaceId,proto3,oneof"` -} - -func (*AddNeighborRequest_PortId) isAddNeighborRequest_Dev() {} - -func (*AddNeighborRequest_InterfaceId) isAddNeighborRequest_Dev() {} - -type isAddNeighborRequest_Ip interface { - isAddNeighborRequest_Ip() -} - -type AddNeighborRequest_IpStr struct { - IpStr string `protobuf:"bytes,2,opt,name=ip_str,json=ipStr,proto3,oneof"` -} - -type AddNeighborRequest_IpBytes struct { - IpBytes []byte `protobuf:"bytes,3,opt,name=ip_bytes,json=ipBytes,proto3,oneof"` -} - -func (*AddNeighborRequest_IpStr) isAddNeighborRequest_Ip() {} - -func (*AddNeighborRequest_IpBytes) isAddNeighborRequest_Ip() {} - -type AddNeighborResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AddNeighborResponse) Reset() { - *x = AddNeighborResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddNeighborResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddNeighborResponse) ProtoMessage() {} - -func (x *AddNeighborResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddNeighborResponse.ProtoReflect.Descriptor instead. -func (*AddNeighborResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{17} -} - -type RemoveNeighborRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Dev: - // - // *RemoveNeighborRequest_PortId - // *RemoveNeighborRequest_InterfaceId - Dev isRemoveNeighborRequest_Dev `protobuf_oneof:"dev"` - // Types that are assignable to Ip: - // - // *RemoveNeighborRequest_IpStr - // *RemoveNeighborRequest_IpBytes - Ip isRemoveNeighborRequest_Ip `protobuf_oneof:"ip"` -} - -func (x *RemoveNeighborRequest) Reset() { - *x = RemoveNeighborRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveNeighborRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveNeighborRequest) ProtoMessage() {} - -func (x *RemoveNeighborRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveNeighborRequest.ProtoReflect.Descriptor instead. -func (*RemoveNeighborRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{18} -} - -func (m *RemoveNeighborRequest) GetDev() isRemoveNeighborRequest_Dev { - if m != nil { - return m.Dev - } - return nil -} - -func (x *RemoveNeighborRequest) GetPortId() string { - if x, ok := x.GetDev().(*RemoveNeighborRequest_PortId); ok { - return x.PortId - } - return "" -} - -func (x *RemoveNeighborRequest) GetInterfaceId() string { - if x, ok := x.GetDev().(*RemoveNeighborRequest_InterfaceId); ok { - return x.InterfaceId - } - return "" -} - -func (m *RemoveNeighborRequest) GetIp() isRemoveNeighborRequest_Ip { - if m != nil { - return m.Ip - } - return nil -} - -func (x *RemoveNeighborRequest) GetIpStr() string { - if x, ok := x.GetIp().(*RemoveNeighborRequest_IpStr); ok { - return x.IpStr - } - return "" -} - -func (x *RemoveNeighborRequest) GetIpBytes() []byte { - if x, ok := x.GetIp().(*RemoveNeighborRequest_IpBytes); ok { - return x.IpBytes - } - return nil -} - -type isRemoveNeighborRequest_Dev interface { - isRemoveNeighborRequest_Dev() -} - -type RemoveNeighborRequest_PortId struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3,oneof"` -} - -type RemoveNeighborRequest_InterfaceId struct { - InterfaceId string `protobuf:"bytes,4,opt,name=interface_id,json=interfaceId,proto3,oneof"` -} - -func (*RemoveNeighborRequest_PortId) isRemoveNeighborRequest_Dev() {} - -func (*RemoveNeighborRequest_InterfaceId) isRemoveNeighborRequest_Dev() {} - -type isRemoveNeighborRequest_Ip interface { - isRemoveNeighborRequest_Ip() -} - -type RemoveNeighborRequest_IpStr struct { - IpStr string `protobuf:"bytes,2,opt,name=ip_str,json=ipStr,proto3,oneof"` -} - -type RemoveNeighborRequest_IpBytes struct { - IpBytes []byte `protobuf:"bytes,3,opt,name=ip_bytes,json=ipBytes,proto3,oneof"` -} - -func (*RemoveNeighborRequest_IpStr) isRemoveNeighborRequest_Ip() {} - -func (*RemoveNeighborRequest_IpBytes) isRemoveNeighborRequest_Ip() {} - -type RemoveNeighborResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RemoveNeighborResponse) Reset() { - *x = RemoveNeighborResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveNeighborResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveNeighborResponse) ProtoMessage() {} - -func (x *RemoveNeighborResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveNeighborResponse.ProtoReflect.Descriptor instead. -func (*RemoveNeighborResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{19} -} - -type AddInterfaceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - VrfId uint32 `protobuf:"varint,2,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` - Mac []byte `protobuf:"bytes,3,opt,name=mac,proto3" json:"mac,omitempty"` - Type InterfaceType `protobuf:"varint,4,opt,name=type,proto3,enum=lemming.dataplane.InterfaceType" json:"type,omitempty"` - PortIds []string `protobuf:"bytes,5,rep,name=port_ids,json=portIds,proto3" json:"port_ids,omitempty"` - Mtu uint64 `protobuf:"varint,6,opt,name=mtu,proto3" json:"mtu,omitempty"` -} - -func (x *AddInterfaceRequest) Reset() { - *x = AddInterfaceRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddInterfaceRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddInterfaceRequest) ProtoMessage() {} - -func (x *AddInterfaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddInterfaceRequest.ProtoReflect.Descriptor instead. -func (*AddInterfaceRequest) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{20} -} - -func (x *AddInterfaceRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *AddInterfaceRequest) GetVrfId() uint32 { - if x != nil { - return x.VrfId - } - return 0 -} - -func (x *AddInterfaceRequest) GetMac() []byte { - if x != nil { - return x.Mac - } - return nil -} - -func (x *AddInterfaceRequest) GetType() InterfaceType { - if x != nil { - return x.Type - } - return InterfaceType_INTERFACE_TYPE_UNSPECIFIED -} - -func (x *AddInterfaceRequest) GetPortIds() []string { - if x != nil { - return x.PortIds - } - return nil -} - -func (x *AddInterfaceRequest) GetMtu() uint64 { - if x != nil { - return x.Mtu - } - return 0 -} - -type AddInterfaceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AddInterfaceResponse) Reset() { - *x = AddInterfaceResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddInterfaceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddInterfaceResponse) ProtoMessage() {} - -func (x *AddInterfaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_dataplane_dataplane_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddInterfaceResponse.ProtoReflect.Descriptor instead. -func (*AddInterfaceResponse) Descriptor() ([]byte, []int) { - return file_proto_dataplane_dataplane_proto_rawDescGZIP(), []int{21} -} - -var File_proto_dataplane_dataplane_proto protoreflect.FileDescriptor - -var file_proto_dataplane_dataplane_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x11, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x1a, 0x28, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x2f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe4, 0x01, 0x0a, 0x07, 0x4e, 0x65, 0x78, 0x74, 0x48, - 0x6f, 0x70, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x06, 0x69, 0x70, 0x5f, 0x73, - 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x05, 0x69, 0x70, 0x53, 0x74, - 0x72, 0x12, 0x1b, 0x0a, 0x08, 0x69, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x48, 0x01, 0x52, 0x07, 0x69, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x48, 0x0a, 0x14, 0x70, 0x72, 0x65, 0x5f, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x73, 0x63, 0x52, 0x12, 0x70, 0x72, - 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x42, 0x05, 0x0a, 0x03, 0x64, 0x65, 0x76, 0x42, 0x04, 0x0a, 0x02, 0x69, 0x70, 0x22, 0x3d, 0x0a, - 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, - 0x68, 0x6f, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x65, 0x6d, - 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x4e, - 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x52, 0x04, 0x68, 0x6f, 0x70, 0x73, 0x22, 0x3d, 0x0a, 0x0d, - 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x49, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x04, 0x68, 0x6f, 0x70, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x04, 0x52, 0x07, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x22, 0x75, 0x0a, 0x0b, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x04, 0x63, 0x69, - 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, - 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x49, 0x70, 0x4d, 0x61, 0x73, 0x6b, 0x48, 0x00, 0x52, 0x04, 0x6d, 0x61, 0x73, - 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x22, 0xcd, 0x02, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x06, - 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, - 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, - 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, - 0x07, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x06, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, - 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, - 0x09, 0x6e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6e, 0x65, - 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0e, 0x6e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x5f, - 0x68, 0x6f, 0x70, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x65, 0x6d, - 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x4e, - 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x08, 0x6e, 0x65, - 0x78, 0x74, 0x48, 0x6f, 0x70, 0x73, 0x12, 0x23, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x42, 0x05, 0x0a, 0x03, 0x68, - 0x6f, 0x70, 0x22, 0xd7, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x64, 0x65, 0x76, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, - 0x44, 0x65, 0x76, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6c, 0x65, 0x6d, - 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x50, - 0x6f, 0x72, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x72, 0x63, 0x22, 0x14, 0x0a, 0x12, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x30, 0x0a, 0x06, 0x49, 0x70, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x12, 0x0a, 0x04, - 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x43, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x49, 0x50, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, - 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x41, 0x64, 0x64, - 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x4e, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, - 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, - 0x17, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5a, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x4e, - 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x35, 0x0a, - 0x08, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x52, 0x07, 0x6e, 0x65, 0x78, - 0x74, 0x48, 0x6f, 0x70, 0x22, 0x14, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, - 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x16, 0x41, - 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, - 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x49, - 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, - 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, - 0x70, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa9, - 0x01, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x64, - 0x12, 0x23, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x06, 0x69, 0x70, 0x5f, 0x73, 0x74, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x05, 0x69, 0x70, 0x53, 0x74, 0x72, 0x12, 0x1b, - 0x0a, 0x08, 0x69, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x48, 0x01, 0x52, 0x07, 0x69, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, - 0x61, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x61, 0x63, 0x42, 0x05, 0x0a, - 0x03, 0x64, 0x65, 0x76, 0x42, 0x04, 0x0a, 0x02, 0x69, 0x70, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, - 0x64, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x65, 0x69, 0x67, - 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x70, - 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, - 0x70, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x06, 0x69, - 0x70, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x05, 0x69, - 0x70, 0x53, 0x74, 0x72, 0x12, 0x1b, 0x0a, 0x08, 0x69, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x01, 0x52, 0x07, 0x69, 0x70, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x42, 0x05, 0x0a, 0x03, 0x64, 0x65, 0x76, 0x42, 0x04, 0x0a, 0x02, 0x69, 0x70, 0x22, 0x18, - 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x61, 0x63, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, - 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, - 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, - 0x75, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x16, 0x0a, 0x14, - 0x41, 0x64, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x7c, 0x0a, 0x0c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, - 0x1a, 0x0a, 0x16, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x50, - 0x4f, 0x52, 0x54, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x50, 0x55, - 0x10, 0x03, 0x2a, 0x60, 0x0a, 0x0c, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x41, 0x43, - 0x4b, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x4f, 0x52, 0x57, 0x41, - 0x52, 0x44, 0x10, 0x02, 0x2a, 0x9a, 0x01, 0x0a, 0x0f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x47, 0x52, 0x4f, 0x55, - 0x50, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x27, 0x0a, 0x23, 0x47, - 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x4c, 0x49, - 0x43, 0x54, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x55, 0x50, - 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, - 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x55, 0x50, 0x44, 0x41, - 0x54, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, - 0x03, 0x2a, 0x83, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x46, 0x41, 0x43, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x46, 0x41, 0x43, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, - 0x49, 0x4e, 0x54, 0x45, 0x52, 0x46, 0x41, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, - 0x4f, 0x4f, 0x50, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x4e, 0x54, - 0x45, 0x52, 0x46, 0x41, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x47, 0x47, 0x52, - 0x45, 0x47, 0x41, 0x54, 0x45, 0x10, 0x03, 0x32, 0xa0, 0x06, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x12, 0x5b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, - 0x6f, 0x72, 0x74, 0x12, 0x24, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, - 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, - 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, - 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x12, 0x24, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, - 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x64, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x12, 0x27, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x50, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, - 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, - 0x48, 0x6f, 0x70, 0x12, 0x24, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, - 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, - 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, - 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, - 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x29, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, - 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, - 0x74, 0x48, 0x6f, 0x70, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, - 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x12, 0x25, 0x2e, - 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, - 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x4e, 0x65, 0x69, 0x67, - 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, - 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, - 0x12, 0x28, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x65, 0x69, 0x67, 0x68, - 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6c, 0x65, 0x6d, - 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, - 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2f, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} - -var ( - file_proto_dataplane_dataplane_proto_rawDescOnce sync.Once - file_proto_dataplane_dataplane_proto_rawDescData = file_proto_dataplane_dataplane_proto_rawDesc -) - -func file_proto_dataplane_dataplane_proto_rawDescGZIP() []byte { - file_proto_dataplane_dataplane_proto_rawDescOnce.Do(func() { - file_proto_dataplane_dataplane_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_dataplane_dataplane_proto_rawDescData) - }) - return file_proto_dataplane_dataplane_proto_rawDescData -} - -var file_proto_dataplane_dataplane_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_proto_dataplane_dataplane_proto_msgTypes = make([]protoimpl.MessageInfo, 22) -var file_proto_dataplane_dataplane_proto_goTypes = []interface{}{ - (PortLocation)(0), // 0: lemming.dataplane.PortLocation - (PacketAction)(0), // 1: lemming.dataplane.PacketAction - (GroupUpdateMode)(0), // 2: lemming.dataplane.GroupUpdateMode - (InterfaceType)(0), // 3: lemming.dataplane.InterfaceType - (*NextHop)(nil), // 4: lemming.dataplane.NextHop - (*NextHopList)(nil), // 5: lemming.dataplane.NextHopList - (*NextHopIDList)(nil), // 6: lemming.dataplane.NextHopIDList - (*RoutePrefix)(nil), // 7: lemming.dataplane.RoutePrefix - (*Route)(nil), // 8: lemming.dataplane.Route - (*CreatePortRequest)(nil), // 9: lemming.dataplane.CreatePortRequest - (*CreatePortResponse)(nil), // 10: lemming.dataplane.CreatePortResponse - (*IpMask)(nil), // 11: lemming.dataplane.IpMask - (*AddIPRouteRequest)(nil), // 12: lemming.dataplane.AddIPRouteRequest - (*AddIPRouteResponse)(nil), // 13: lemming.dataplane.AddIPRouteResponse - (*RemoveIPRouteRequest)(nil), // 14: lemming.dataplane.RemoveIPRouteRequest - (*RemoveIPRouteResponse)(nil), // 15: lemming.dataplane.RemoveIPRouteResponse - (*AddNextHopRequest)(nil), // 16: lemming.dataplane.AddNextHopRequest - (*AddNextHopResponse)(nil), // 17: lemming.dataplane.AddNextHopResponse - (*AddNextHopGroupRequest)(nil), // 18: lemming.dataplane.AddNextHopGroupRequest - (*AddNextHopGroupResponse)(nil), // 19: lemming.dataplane.AddNextHopGroupResponse - (*AddNeighborRequest)(nil), // 20: lemming.dataplane.AddNeighborRequest - (*AddNeighborResponse)(nil), // 21: lemming.dataplane.AddNeighborResponse - (*RemoveNeighborRequest)(nil), // 22: lemming.dataplane.RemoveNeighborRequest - (*RemoveNeighborResponse)(nil), // 23: lemming.dataplane.RemoveNeighborResponse - (*AddInterfaceRequest)(nil), // 24: lemming.dataplane.AddInterfaceRequest - (*AddInterfaceResponse)(nil), // 25: lemming.dataplane.AddInterfaceResponse - (*forwarding.ActionDesc)(nil), // 26: forwarding.ActionDesc - (forwarding.PortType)(0), // 27: forwarding.PortType -} -var file_proto_dataplane_dataplane_proto_depIdxs = []int32{ - 26, // 0: lemming.dataplane.NextHop.pre_transmit_actions:type_name -> forwarding.ActionDesc - 4, // 1: lemming.dataplane.NextHopList.hops:type_name -> lemming.dataplane.NextHop - 11, // 2: lemming.dataplane.RoutePrefix.mask:type_name -> lemming.dataplane.IpMask - 7, // 3: lemming.dataplane.Route.prefix:type_name -> lemming.dataplane.RoutePrefix - 1, // 4: lemming.dataplane.Route.action:type_name -> lemming.dataplane.PacketAction - 5, // 5: lemming.dataplane.Route.next_hops:type_name -> lemming.dataplane.NextHopList - 27, // 6: lemming.dataplane.CreatePortRequest.type:type_name -> forwarding.PortType - 0, // 7: lemming.dataplane.CreatePortRequest.location:type_name -> lemming.dataplane.PortLocation - 8, // 8: lemming.dataplane.AddIPRouteRequest.route:type_name -> lemming.dataplane.Route - 7, // 9: lemming.dataplane.RemoveIPRouteRequest.prefix:type_name -> lemming.dataplane.RoutePrefix - 4, // 10: lemming.dataplane.AddNextHopRequest.next_hop:type_name -> lemming.dataplane.NextHop - 6, // 11: lemming.dataplane.AddNextHopGroupRequest.list:type_name -> lemming.dataplane.NextHopIDList - 2, // 12: lemming.dataplane.AddNextHopGroupRequest.mode:type_name -> lemming.dataplane.GroupUpdateMode - 3, // 13: lemming.dataplane.AddInterfaceRequest.type:type_name -> lemming.dataplane.InterfaceType - 9, // 14: lemming.dataplane.Dataplane.CreatePort:input_type -> lemming.dataplane.CreatePortRequest - 12, // 15: lemming.dataplane.Dataplane.AddIPRoute:input_type -> lemming.dataplane.AddIPRouteRequest - 14, // 16: lemming.dataplane.Dataplane.RemoveIPRoute:input_type -> lemming.dataplane.RemoveIPRouteRequest - 16, // 17: lemming.dataplane.Dataplane.AddNextHop:input_type -> lemming.dataplane.AddNextHopRequest - 18, // 18: lemming.dataplane.Dataplane.AddNextHopGroup:input_type -> lemming.dataplane.AddNextHopGroupRequest - 20, // 19: lemming.dataplane.Dataplane.AddNeighbor:input_type -> lemming.dataplane.AddNeighborRequest - 22, // 20: lemming.dataplane.Dataplane.RemoveNeighbor:input_type -> lemming.dataplane.RemoveNeighborRequest - 24, // 21: lemming.dataplane.Dataplane.AddInterface:input_type -> lemming.dataplane.AddInterfaceRequest - 10, // 22: lemming.dataplane.Dataplane.CreatePort:output_type -> lemming.dataplane.CreatePortResponse - 13, // 23: lemming.dataplane.Dataplane.AddIPRoute:output_type -> lemming.dataplane.AddIPRouteResponse - 15, // 24: lemming.dataplane.Dataplane.RemoveIPRoute:output_type -> lemming.dataplane.RemoveIPRouteResponse - 17, // 25: lemming.dataplane.Dataplane.AddNextHop:output_type -> lemming.dataplane.AddNextHopResponse - 19, // 26: lemming.dataplane.Dataplane.AddNextHopGroup:output_type -> lemming.dataplane.AddNextHopGroupResponse - 21, // 27: lemming.dataplane.Dataplane.AddNeighbor:output_type -> lemming.dataplane.AddNeighborResponse - 23, // 28: lemming.dataplane.Dataplane.RemoveNeighbor:output_type -> lemming.dataplane.RemoveNeighborResponse - 25, // 29: lemming.dataplane.Dataplane.AddInterface:output_type -> lemming.dataplane.AddInterfaceResponse - 22, // [22:30] is the sub-list for method output_type - 14, // [14:22] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name -} - -func init() { file_proto_dataplane_dataplane_proto_init() } -func file_proto_dataplane_dataplane_proto_init() { - if File_proto_dataplane_dataplane_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_proto_dataplane_dataplane_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NextHop); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NextHopList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NextHopIDList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RoutePrefix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Route); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreatePortRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreatePortResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IpMask); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddIPRouteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddIPRouteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveIPRouteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveIPRouteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddNextHopRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddNextHopResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddNextHopGroupRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddNextHopGroupResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_dataplane_dataplane_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddNeighborRequest); i { +func init() { file_proto_dataplane_dataplane_proto_init() } +func file_proto_dataplane_dataplane_proto_init() { + if File_proto_dataplane_dataplane_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_dataplane_dataplane_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OCInterface); i { case 0: return &v.state case 1: @@ -2238,8 +668,8 @@ func file_proto_dataplane_dataplane_proto_init() { return nil } } - file_proto_dataplane_dataplane_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddNeighborResponse); i { + file_proto_dataplane_dataplane_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GUE); i { case 0: return &v.state case 1: @@ -2250,8 +680,8 @@ func file_proto_dataplane_dataplane_proto_init() { return nil } } - file_proto_dataplane_dataplane_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNeighborRequest); i { + file_proto_dataplane_dataplane_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NextHop); i { case 0: return &v.state case 1: @@ -2262,8 +692,8 @@ func file_proto_dataplane_dataplane_proto_init() { return nil } } - file_proto_dataplane_dataplane_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNeighborResponse); i { + file_proto_dataplane_dataplane_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NextHopList); i { case 0: return &v.state case 1: @@ -2274,8 +704,8 @@ func file_proto_dataplane_dataplane_proto_init() { return nil } } - file_proto_dataplane_dataplane_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddInterfaceRequest); i { + file_proto_dataplane_dataplane_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RoutePrefix); i { case 0: return &v.state case 1: @@ -2286,8 +716,8 @@ func file_proto_dataplane_dataplane_proto_init() { return nil } } - file_proto_dataplane_dataplane_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddInterfaceResponse); i { + file_proto_dataplane_dataplane_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Route); i { case 0: return &v.state case 1: @@ -2299,47 +729,22 @@ func file_proto_dataplane_dataplane_proto_init() { } } } - file_proto_dataplane_dataplane_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*NextHop_Port)(nil), - (*NextHop_Interface)(nil), - (*NextHop_IpStr)(nil), - (*NextHop_IpBytes)(nil), - } - file_proto_dataplane_dataplane_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*RoutePrefix_Cidr)(nil), - (*RoutePrefix_Mask)(nil), - } - file_proto_dataplane_dataplane_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*Route_PortId)(nil), - (*Route_NextHopId)(nil), - (*Route_NextHopGroupId)(nil), - (*Route_NextHops)(nil), - (*Route_InterfaceId)(nil), + file_proto_dataplane_dataplane_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*NextHop_Gue)(nil), } file_proto_dataplane_dataplane_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*CreatePortRequest_KernelDev)(nil), - } - file_proto_dataplane_dataplane_proto_msgTypes[16].OneofWrappers = []interface{}{ - (*AddNeighborRequest_PortId)(nil), - (*AddNeighborRequest_InterfaceId)(nil), - (*AddNeighborRequest_IpStr)(nil), - (*AddNeighborRequest_IpBytes)(nil), - } - file_proto_dataplane_dataplane_proto_msgTypes[18].OneofWrappers = []interface{}{ - (*RemoveNeighborRequest_PortId)(nil), - (*RemoveNeighborRequest_InterfaceId)(nil), - (*RemoveNeighborRequest_IpStr)(nil), - (*RemoveNeighborRequest_IpBytes)(nil), + (*Route_NextHops)(nil), + (*Route_Interface)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_dataplane_dataplane_proto_rawDesc, - NumEnums: 4, - NumMessages: 22, + NumEnums: 2, + NumMessages: 6, NumExtensions: 0, - NumServices: 1, + NumServices: 0, }, GoTypes: file_proto_dataplane_dataplane_proto_goTypes, DependencyIndexes: file_proto_dataplane_dataplane_proto_depIdxs, @@ -2351,335 +756,3 @@ func file_proto_dataplane_dataplane_proto_init() { file_proto_dataplane_dataplane_proto_goTypes = nil file_proto_dataplane_dataplane_proto_depIdxs = nil } - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// DataplaneClient is the client API for Dataplane service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type DataplaneClient interface { - CreatePort(ctx context.Context, in *CreatePortRequest, opts ...grpc.CallOption) (*CreatePortResponse, error) - AddIPRoute(ctx context.Context, in *AddIPRouteRequest, opts ...grpc.CallOption) (*AddIPRouteResponse, error) - RemoveIPRoute(ctx context.Context, in *RemoveIPRouteRequest, opts ...grpc.CallOption) (*RemoveIPRouteResponse, error) - AddNextHop(ctx context.Context, in *AddNextHopRequest, opts ...grpc.CallOption) (*AddNextHopResponse, error) - AddNextHopGroup(ctx context.Context, in *AddNextHopGroupRequest, opts ...grpc.CallOption) (*AddNextHopGroupResponse, error) - AddNeighbor(ctx context.Context, in *AddNeighborRequest, opts ...grpc.CallOption) (*AddNeighborResponse, error) - RemoveNeighbor(ctx context.Context, in *RemoveNeighborRequest, opts ...grpc.CallOption) (*RemoveNeighborResponse, error) - AddInterface(ctx context.Context, in *AddInterfaceRequest, opts ...grpc.CallOption) (*AddInterfaceResponse, error) -} - -type dataplaneClient struct { - cc grpc.ClientConnInterface -} - -func NewDataplaneClient(cc grpc.ClientConnInterface) DataplaneClient { - return &dataplaneClient{cc} -} - -func (c *dataplaneClient) CreatePort(ctx context.Context, in *CreatePortRequest, opts ...grpc.CallOption) (*CreatePortResponse, error) { - out := new(CreatePortResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/CreatePort", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) AddIPRoute(ctx context.Context, in *AddIPRouteRequest, opts ...grpc.CallOption) (*AddIPRouteResponse, error) { - out := new(AddIPRouteResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/AddIPRoute", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) RemoveIPRoute(ctx context.Context, in *RemoveIPRouteRequest, opts ...grpc.CallOption) (*RemoveIPRouteResponse, error) { - out := new(RemoveIPRouteResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/RemoveIPRoute", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) AddNextHop(ctx context.Context, in *AddNextHopRequest, opts ...grpc.CallOption) (*AddNextHopResponse, error) { - out := new(AddNextHopResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/AddNextHop", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) AddNextHopGroup(ctx context.Context, in *AddNextHopGroupRequest, opts ...grpc.CallOption) (*AddNextHopGroupResponse, error) { - out := new(AddNextHopGroupResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/AddNextHopGroup", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) AddNeighbor(ctx context.Context, in *AddNeighborRequest, opts ...grpc.CallOption) (*AddNeighborResponse, error) { - out := new(AddNeighborResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/AddNeighbor", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) RemoveNeighbor(ctx context.Context, in *RemoveNeighborRequest, opts ...grpc.CallOption) (*RemoveNeighborResponse, error) { - out := new(RemoveNeighborResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/RemoveNeighbor", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *dataplaneClient) AddInterface(ctx context.Context, in *AddInterfaceRequest, opts ...grpc.CallOption) (*AddInterfaceResponse, error) { - out := new(AddInterfaceResponse) - err := c.cc.Invoke(ctx, "/lemming.dataplane.Dataplane/AddInterface", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// DataplaneServer is the server API for Dataplane service. -type DataplaneServer interface { - CreatePort(context.Context, *CreatePortRequest) (*CreatePortResponse, error) - AddIPRoute(context.Context, *AddIPRouteRequest) (*AddIPRouteResponse, error) - RemoveIPRoute(context.Context, *RemoveIPRouteRequest) (*RemoveIPRouteResponse, error) - AddNextHop(context.Context, *AddNextHopRequest) (*AddNextHopResponse, error) - AddNextHopGroup(context.Context, *AddNextHopGroupRequest) (*AddNextHopGroupResponse, error) - AddNeighbor(context.Context, *AddNeighborRequest) (*AddNeighborResponse, error) - RemoveNeighbor(context.Context, *RemoveNeighborRequest) (*RemoveNeighborResponse, error) - AddInterface(context.Context, *AddInterfaceRequest) (*AddInterfaceResponse, error) -} - -// UnimplementedDataplaneServer can be embedded to have forward compatible implementations. -type UnimplementedDataplaneServer struct { -} - -func (*UnimplementedDataplaneServer) CreatePort(context.Context, *CreatePortRequest) (*CreatePortResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreatePort not implemented") -} -func (*UnimplementedDataplaneServer) AddIPRoute(context.Context, *AddIPRouteRequest) (*AddIPRouteResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddIPRoute not implemented") -} -func (*UnimplementedDataplaneServer) RemoveIPRoute(context.Context, *RemoveIPRouteRequest) (*RemoveIPRouteResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RemoveIPRoute not implemented") -} -func (*UnimplementedDataplaneServer) AddNextHop(context.Context, *AddNextHopRequest) (*AddNextHopResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddNextHop not implemented") -} -func (*UnimplementedDataplaneServer) AddNextHopGroup(context.Context, *AddNextHopGroupRequest) (*AddNextHopGroupResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddNextHopGroup not implemented") -} -func (*UnimplementedDataplaneServer) AddNeighbor(context.Context, *AddNeighborRequest) (*AddNeighborResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddNeighbor not implemented") -} -func (*UnimplementedDataplaneServer) RemoveNeighbor(context.Context, *RemoveNeighborRequest) (*RemoveNeighborResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RemoveNeighbor not implemented") -} -func (*UnimplementedDataplaneServer) AddInterface(context.Context, *AddInterfaceRequest) (*AddInterfaceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddInterface not implemented") -} - -func RegisterDataplaneServer(s *grpc.Server, srv DataplaneServer) { - s.RegisterService(&_Dataplane_serviceDesc, srv) -} - -func _Dataplane_CreatePort_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreatePortRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).CreatePort(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/CreatePort", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).CreatePort(ctx, req.(*CreatePortRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_AddIPRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddIPRouteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).AddIPRoute(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/AddIPRoute", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).AddIPRoute(ctx, req.(*AddIPRouteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_RemoveIPRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RemoveIPRouteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).RemoveIPRoute(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/RemoveIPRoute", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).RemoveIPRoute(ctx, req.(*RemoveIPRouteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_AddNextHop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddNextHopRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).AddNextHop(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/AddNextHop", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).AddNextHop(ctx, req.(*AddNextHopRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_AddNextHopGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddNextHopGroupRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).AddNextHopGroup(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/AddNextHopGroup", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).AddNextHopGroup(ctx, req.(*AddNextHopGroupRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_AddNeighbor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddNeighborRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).AddNeighbor(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/AddNeighbor", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).AddNeighbor(ctx, req.(*AddNeighborRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_RemoveNeighbor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RemoveNeighborRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).RemoveNeighbor(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/RemoveNeighbor", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).RemoveNeighbor(ctx, req.(*RemoveNeighborRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Dataplane_AddInterface_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddInterfaceRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DataplaneServer).AddInterface(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/lemming.dataplane.Dataplane/AddInterface", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DataplaneServer).AddInterface(ctx, req.(*AddInterfaceRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Dataplane_serviceDesc = grpc.ServiceDesc{ - ServiceName: "lemming.dataplane.Dataplane", - HandlerType: (*DataplaneServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "CreatePort", - Handler: _Dataplane_CreatePort_Handler, - }, - { - MethodName: "AddIPRoute", - Handler: _Dataplane_AddIPRoute_Handler, - }, - { - MethodName: "RemoveIPRoute", - Handler: _Dataplane_RemoveIPRoute_Handler, - }, - { - MethodName: "AddNextHop", - Handler: _Dataplane_AddNextHop_Handler, - }, - { - MethodName: "AddNextHopGroup", - Handler: _Dataplane_AddNextHopGroup_Handler, - }, - { - MethodName: "AddNeighbor", - Handler: _Dataplane_AddNeighbor_Handler, - }, - { - MethodName: "RemoveNeighbor", - Handler: _Dataplane_RemoveNeighbor_Handler, - }, - { - MethodName: "AddInterface", - Handler: _Dataplane_AddInterface_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "proto/dataplane/dataplane.proto", -} diff --git a/proto/dataplane/dataplane.proto b/proto/dataplane/dataplane.proto index f8166d9a..6a623305 100644 --- a/proto/dataplane/dataplane.proto +++ b/proto/dataplane/dataplane.proto @@ -16,55 +16,44 @@ syntax = "proto3"; package lemming.dataplane; -import "proto/forwarding/forwarding_action.proto"; -import "proto/forwarding/forwarding_port.proto"; - option go_package = "github.com/openconfig/lemming/proto/dataplane"; -message NextHop { - oneof dev { - string port = 1; - string interface = 2; - } +message OCInterface { + string interface = 1; + uint32 subinterface = 2; +} - oneof ip { - string ip_str = 3; - bytes ip_bytes = 4; - } +message GUE { + bytes src_ip = 1; + bytes dst_ip = 2; + uint32 dst_port = 3; + bool is_v6 = 4; +} - uint64 weight = 5; - // pre_transmit_actions are extra actions that are applied just prior to - // transmitting the packet to the output port (at which time the output - // actions are applied). - repeated forwarding.ActionDesc pre_transmit_actions = 6; +message NextHop { + OCInterface interface = 1; + string next_hop_ip = 2; + oneof encap { + GUE gue = 3; + } } message NextHopList { repeated NextHop hops = 1; -} - -message NextHopIDList { - repeated uint64 hops = 1; repeated uint64 weights = 2; } message RoutePrefix { - oneof prefix { // Specify either cidr string or ip and mask bytes. - string cidr = 1; - IpMask mask = 2; - } - uint64 vrf_id = 3; + string cidr = 1; + string network_instance = 2; } message Route { RoutePrefix prefix = 1; PacketAction action = 2; oneof hop { - string port_id = 3; // Id of the output port. - uint64 next_hop_id = 4; // Id of the next hop. - uint64 next_hop_group_id = 5; // Id of the next hop group - NextHopList next_hops = 6; // Implicitly create next hop, next hop groups. - string interface_id = 7; + NextHopList next_hops = 3; // Implicitly create next hop, next hop groups. + OCInterface interface = 4; // For connected routes. } } @@ -75,138 +64,8 @@ enum PortLocation { PORT_LOCATION_CPU = 3; } - -message CreatePortRequest { - forwarding.PortType type = 1; - string id = 2; - oneof src { - // Name of the linux kernel device to use for the port (eg eth0). - string kernel_dev = 3; - } - // For internal ports (TAP interface), - // the id of the corresponding port for punt rules. - string external_port = 4; - PortLocation location = 5; -} - -message CreatePortResponse { - -} - -message IpMask { - bytes addr = 1; - bytes mask = 2; -} - enum PacketAction { PACKET_ACTION_UNSPECIFIED = 0; PACKET_ACTION_DROP = 1; PACKET_ACTION_FORWARD = 2; -} - -message AddIPRouteRequest { - Route route = 1; -} - -message AddIPRouteResponse { - -} - -message RemoveIPRouteRequest { - RoutePrefix prefix = 1; -} - -message RemoveIPRouteResponse { - -} - -message AddNextHopRequest { - uint64 id = 1; - NextHop next_hop = 2; - -} - -message AddNextHopResponse { - -} - -enum GroupUpdateMode { - GROUP_UPDATE_MODE_UNSPECIFIED = 0; - GROUP_UPDATE_MODE_ERROR_ON_CONFLICT = 1; - GROUP_UPDATE_MODE_APPEND = 2; - GROUP_UPDATE_MODE_REPLACE = 3; -} - - -message AddNextHopGroupRequest { - uint64 id = 1; - NextHopIDList list = 2; - GroupUpdateMode mode = 3; -} - -message AddNextHopGroupResponse { - -} - -message AddNeighborRequest { - oneof dev { - string port_id = 1; - string interface_id = 5; - } - oneof ip { - string ip_str = 2; - bytes ip_bytes = 3; - } - bytes mac = 4; -} - -message AddNeighborResponse { - -} - -message RemoveNeighborRequest { - oneof dev { - string port_id = 1; - string interface_id = 4; - } - oneof ip { - string ip_str = 2; - bytes ip_bytes = 3; - } -} - -message RemoveNeighborResponse { - -} - -enum InterfaceType { - INTERFACE_TYPE_UNSPECIFIED = 0; - INTERFACE_TYPE_PORT = 1; - INTERFACE_TYPE_LOOPBACK = 2; - INTERFACE_TYPE_AGGREGATE = 3; -} - -message AddInterfaceRequest { - string id = 1; - uint32 vrf_id = 2; - bytes mac = 3; - InterfaceType type = 4; - repeated string port_ids = 5; - uint64 mtu = 6; -} - -message AddInterfaceResponse { - -} - -service Dataplane { - rpc CreatePort(CreatePortRequest) returns (CreatePortResponse) {} - rpc AddIPRoute(AddIPRouteRequest) returns (AddIPRouteResponse) {} - rpc RemoveIPRoute(RemoveIPRouteRequest) returns (RemoveIPRouteResponse) {} - rpc AddNextHop(AddNextHopRequest) returns (AddNextHopResponse) {} - rpc AddNextHopGroup(AddNextHopGroupRequest) - returns (AddNextHopGroupResponse) {} - rpc AddNeighbor(AddNeighborRequest) returns (AddNeighborResponse) {} - rpc RemoveNeighbor(RemoveNeighborRequest) returns (RemoveNeighborResponse) {} - rpc AddInterface(AddInterfaceRequest) returns (AddInterfaceResponse) {} } \ No newline at end of file diff --git a/sysrib/BUILD b/sysrib/BUILD index e7df6519..89cf2913 100644 --- a/sysrib/BUILD +++ b/sysrib/BUILD @@ -15,18 +15,15 @@ go_library( importpath = "github.com/openconfig/lemming/sysrib", visibility = ["//visibility:public"], deps = [ - "//dataplane/handlers", + "//dataplane/dplanerc", "//gnmi/fakedevice", "//gnmi/gnmiclient", "//gnmi/oc", "//gnmi/oc/ocpath", "//proto/dataplane", - "//proto/forwarding", "//proto/sysrib", "@com_github_golang_glog//:glog", "@com_github_google_go_cmp//cmp", - "@com_github_google_gopacket//:gopacket", - "@com_github_google_gopacket//layers", "@com_github_kentik_patricia//:patricia", "@com_github_kentik_patricia//generics_tree", "@com_github_openconfig_gnmi//proto/gnmi", @@ -59,12 +56,9 @@ go_test( "//gnmi/oc", "//gnmi/oc/ocpath", "//proto/dataplane", - "//proto/forwarding", "//proto/sysrib", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", - "@com_github_google_gopacket//:gopacket", - "@com_github_google_gopacket//layers", "@com_github_openconfig_gnmi//proto/gnmi", "@com_github_openconfig_gribigo//afthelper", "@com_github_openconfig_ygnmi//schemaless", diff --git a/sysrib/connected.go b/sysrib/connected.go index 48a58448..5e476177 100644 --- a/sysrib/connected.go +++ b/sysrib/connected.go @@ -19,10 +19,11 @@ import ( "fmt" log "github.com/golang/glog" + "github.com/openconfig/ygnmi/ygnmi" + "github.com/openconfig/lemming/gnmi/fakedevice" "github.com/openconfig/lemming/gnmi/oc" "github.com/openconfig/lemming/gnmi/oc/ocpath" - "github.com/openconfig/ygnmi/ygnmi" ) // monitorConnectedIntfs starts a gothread to check for connected prefixes from @@ -37,10 +38,12 @@ func (s *Server) monitorConnectedIntfs(ctx context.Context, yclient *ygnmi.Clien ocpath.Root().InterfaceAny().Subinterface(0).Ipv4().AddressAny().PrefixLength().State(), ocpath.Root().InterfaceAny().Subinterface(0).Ipv6().AddressAny().Ip().State(), ocpath.Root().InterfaceAny().Subinterface(0).Ipv6().AddressAny().PrefixLength().State(), + ocpath.Root().InterfaceAny().Subinterface(0).Ifindex().State(), + ocpath.Root().InterfaceAny().Subinterface(0).Enabled().State(), ) prevIntfs := map[connectedRoute]struct{}{} - + log.Infof("starting connected route watcher") interfaceWatcher := ygnmi.Watch( ctx, yclient, @@ -50,6 +53,7 @@ func (s *Server) monitorConnectedIntfs(ctx context.Context, yclient *ygnmi.Clien currentIntfs := map[connectedRoute]struct{}{} if ok { for name, intf := range interfaceMap { + log.Infof("got interface update: %v intf.Enabled %v, intf.Ifindex %v", name, intf.Enabled, intf.Ifindex) if intf.Enabled != nil && intf.Ifindex != nil { ifindex := intf.GetIfindex() s.setInterface(ctx, name, int32(ifindex), intf.GetEnabled()) diff --git a/sysrib/server.go b/sysrib/server.go index c0cfd063..8303b110 100644 --- a/sysrib/server.go +++ b/sysrib/server.go @@ -28,15 +28,13 @@ import ( log "github.com/golang/glog" "github.com/google/go-cmp/cmp" - "github.com/google/gopacket" - "github.com/google/gopacket/layers" "github.com/openconfig/gribigo/afthelper" "github.com/openconfig/ygnmi/ygnmi" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/openconfig/lemming/dataplane/handlers" + "github.com/openconfig/lemming/dataplane/dplanerc" "github.com/openconfig/lemming/gnmi/fakedevice" "github.com/openconfig/lemming/gnmi/oc" "github.com/openconfig/lemming/gnmi/oc/ocpath" @@ -44,7 +42,6 @@ import ( gpb "github.com/openconfig/gnmi/proto/gnmi" dpb "github.com/openconfig/lemming/proto/dataplane" - fwdpb "github.com/openconfig/lemming/proto/forwarding" sysribpb "github.com/openconfig/lemming/proto/sysrib" ) @@ -118,7 +115,7 @@ func (d *dplane) programRoute(ctx context.Context, r *ResolvedRoute) error { if err != nil { return err } - _, err = ygnmi.Replace(ctx, d.Client, handlers.RouteQuery(rr.GetPrefix().GetVrfId(), rr.GetPrefix().GetCidr()), rr, ygnmi.WithSetFallbackEncoding()) + _, err = ygnmi.Replace(ctx, d.Client, dplanerc.RouteQuery(rr.GetPrefix().GetNetworkInstance(), r.Prefix), rr, ygnmi.WithSetFallbackEncoding()) return err } @@ -129,7 +126,7 @@ func (d *dplane) deprogramRoute(ctx context.Context, r *ResolvedRoute) error { if err != nil { return err } - _, err = ygnmi.Delete(ctx, d.Client, handlers.RouteQuery(rr.GetPrefix().GetVrfId(), rr.GetPrefix().GetCidr())) + _, err = ygnmi.Delete(ctx, d.Client, dplanerc.RouteQuery(rr.GetPrefix().GetNetworkInstance(), r.Prefix)) return err } @@ -375,106 +372,77 @@ func prefixString(prefix *sysribpb.Prefix) (string, error) { } } -// gueActions generates the forwarding actions that encapsulates a packet with -// a UDP and then an IP header using the information from gueHeaders. -// -// - isRouteV4 indicates whether the route is a v4/v6-mapped v4 route or a v6 route. -func gueActions(isRouteV4 bool, gueHeaders GUEHeaders) ([]*fwdpb.ActionDesc, error) { - var ip gopacket.SerializableLayer - var headerID fwdpb.PacketHeaderId - if !gueHeaders.isV6 { - ip = &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: gueHeaders.srcIP4[:], - DstIP: gueHeaders.dstIP4[:], - } - headerID = fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4 - } else { - ip = &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: gueHeaders.srcIP6[:], - DstIP: gueHeaders.dstIP6[:], - } - headerID = fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP6 - } - - udp := &layers.UDP{ - SrcPort: 0, // TODO(wenbli): Implement hashing for srcPort. - Length: 34, // TODO(wenbli): Figure out how to not make this hardcoded. - } - if isRouteV4 { - udp.DstPort = layers.UDPPort(gueHeaders.dstPortv4) - } else { - udp.DstPort = layers.UDPPort(gueHeaders.dstPortv6) - } - - buf := gopacket.NewSerializeBuffer() - if err := gopacket.SerializeLayers(buf, gopacket.SerializeOptions{}, ip, udp); err != nil { - return nil, fmt.Errorf("failed to serialize GUE headers: %v", err) - } - - return []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: headerID, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - // After the UDP header, the rest of the packet (original packet) will be classified as payload. - Prepend: buf.Bytes(), - }, - }, - }}, nil -} - func resolvedRouteToRouteRequest(r *ResolvedRoute) (*dpb.Route, error) { - vrfID, err := niNameToVrfID(r.NIName) - if err != nil { - return nil, err - } - pfx, err := netip.ParsePrefix(r.Prefix) if err != nil { log.Errorf("Route prefix cannot be parsed: %v", err) return nil, err } - - var nexthops []*dpb.NextHop - for nh := range r.Nexthops { - var actions []*fwdpb.ActionDesc - if nh.HasGUE() { - if actions, err = gueActions(pfx.Addr().Is4() || pfx.Addr().Is4In6(), nh.GUEHeaders); err != nil { - return nil, fmt.Errorf("error retrieving GUE actions: %v", err) + // Connected routes are routes with a single next hop with no address. + // TODO: Include a better signal for this. + if len(r.Nexthops) == 1 { + for nh := range r.Nexthops { + if nh.Address == "" { + return &dpb.Route{ + Prefix: &dpb.RoutePrefix{ + NetworkInstance: r.NIName, + Cidr: r.Prefix, + }, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: nh.Port.Name, + Subinterface: nh.Port.Subinterface, + }, + }, + }, nil } } + } + + nexthops := &dpb.NextHopList{} + for nh := range r.Nexthops { dnh := &dpb.NextHop{ - Dev: &dpb.NextHop_Port{ - Port: nh.Port.Name, + Interface: &dpb.OCInterface{ + Interface: nh.Port.Name, + Subinterface: nh.Port.Subinterface, }, - Weight: nh.Weight, - PreTransmitActions: actions, + NextHopIp: nh.Address, } - if nh.Address != "" { - dnh.Ip = &dpb.NextHop_IpStr{IpStr: nh.Address} + if nh.HasGUE() { + if !nh.GUEHeaders.isV6 { + dnh.Encap = &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: nh.GUEHeaders.srcIP4[:], + DstIp: nh.GUEHeaders.dstIP4[:], + IsV6: nh.GUEHeaders.isV6, + }, + } + } else { + dnh.Encap = &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: nh.GUEHeaders.srcIP6[:], + DstIp: nh.GUEHeaders.dstIP6[:], + IsV6: nh.GUEHeaders.isV6, + }, + } + } + if pfx.Addr().Is4() || pfx.Addr().Is4In6() { + dnh.GetGue().DstPort = uint32(nh.GUEHeaders.dstPortv4) + } else { + dnh.GetGue().DstPort = uint32(nh.GUEHeaders.dstPortv6) + } } - nexthops = append(nexthops, dnh) + nexthops.Hops = append(nexthops.Hops, dnh) + nexthops.Weights = append(nexthops.Weights, nh.Weight) } return &dpb.Route{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(vrfID), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: r.Prefix, - }, + NetworkInstance: r.NIName, + Cidr: r.Prefix, }, Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{Hops: nexthops}, + NextHops: nexthops, }, }, nil } diff --git a/sysrib/server_test.go b/sysrib/server_test.go index 5e79fec8..cd6f2235 100644 --- a/sysrib/server_test.go +++ b/sysrib/server_test.go @@ -25,20 +25,18 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/gopacket" - "github.com/google/gopacket/layers" - "github.com/openconfig/lemming/gnmi" - "github.com/openconfig/lemming/gnmi/gnmiclient" - "github.com/openconfig/lemming/gnmi/oc" - "github.com/openconfig/lemming/gnmi/oc/ocpath" "github.com/openconfig/ygnmi/schemaless" "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" "google.golang.org/grpc" "google.golang.org/protobuf/testing/protocmp" + "github.com/openconfig/lemming/gnmi" + "github.com/openconfig/lemming/gnmi/gnmiclient" + "github.com/openconfig/lemming/gnmi/oc" + "github.com/openconfig/lemming/gnmi/oc/ocpath" + dpb "github.com/openconfig/lemming/proto/dataplane" - fwdpb "github.com/openconfig/lemming/proto/forwarding" pb "github.com/openconfig/lemming/proto/sysrib" ) @@ -116,9 +114,10 @@ func mapAddressTo6Bytes(v4Address [4]byte) [16]byte { return ipv6Bytes } -func mapAddressTo6BytesSlice(v4Address [4]byte) []byte { - r := mapAddressTo6Bytes(v4Address) - return r[:] +func mapAddressSliceTo6BytesSlice(v4Address []byte) []byte { + ipv6Bytes := []byte{0x20, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + copy(ipv6Bytes[v4v6ConversionStartPos:], v4Address) + return ipv6Bytes } func mapPrefixLenTo6(pfxLen int) int { @@ -168,30 +167,18 @@ func mapAddressTo6(t *testing.T, addrStr string) string { } func mapResolvedRouteTo6(t *testing.T, route *dpb.Route) { - route.Prefix.Prefix = &dpb.RoutePrefix_Cidr{Cidr: mapAddressTo6(t, route.Prefix.GetCidr())} + route.Prefix.Cidr = mapAddressTo6(t, route.Prefix.GetCidr()) for _, nh := range route.GetNextHops().GetHops() { - if nh.GetIpStr() != "" { - nh.Ip = &dpb.NextHop_IpStr{IpStr: mapAddressTo6(t, nh.GetIpStr())} + if nh.GetNextHopIp() != "" { + nh.NextHopIp = mapAddressTo6(t, nh.GetNextHopIp()) } - for _, pta := range nh.PreTransmitActions { - if pta.GetReparse().GetHeaderId() == fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4 { - pta.GetReparse().HeaderId = fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP6 - } + if nh.GetGue() != nil { + nh.GetGue().DstIp = mapAddressSliceTo6BytesSlice(nh.GetGue().DstIp) + nh.GetGue().SrcIp = mapAddressSliceTo6BytesSlice(nh.GetGue().SrcIp) } } } -func selectGUEHeaders(t *testing.T, v4 bool, layers ...gopacket.SerializableLayer) []gopacket.SerializableLayer { - layerN := len(layers) - if layerN == 0 || layerN%2 != 0 { - t.Fatalf("Input layers is not even and non-zero: %v", layerN) - } - if v4 { - return layers[:layerN/2] - } - return layers[layerN/2:] -} - func mapPrefixTo6(t *testing.T, prefix *pb.Prefix) { if prefix.Family == pb.Prefix_FAMILY_IPV4 { prefix.Family = pb.Prefix_FAMILY_IPV6 @@ -244,87 +231,52 @@ func getConnectedIntfSetupVarsV4() ([]*AddIntfAction, []*dpb.Route) { niName: "DEFAULT", }}, []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.2.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.2.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth1", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth1", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.3.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.3.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth2", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth2", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.4.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.4.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth3", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth3", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.5.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.5.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth4", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth4", }, }, }} @@ -468,55 +420,49 @@ func TestServer(t *testing.T) { }}, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.5.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth4", + NextHopIp: "192.168.5.42", + Interface: &dpb.OCInterface{ + Interface: "eth4", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.5.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth4", + NextHopIp: "192.168.5.42", + Interface: &dpb.OCInterface{ + Interface: "eth4", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.5.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth4", + NextHopIp: "192.168.5.42", + Interface: &dpb.OCInterface{ + Interface: "eth4", }, - Weight: 0, }}, }, }, @@ -608,19 +554,17 @@ func TestServer(t *testing.T) { }}, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -698,25 +642,22 @@ func TestServer(t *testing.T) { }}, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0, 0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.2.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth1", + NextHopIp: "192.168.2.42", + Interface: &dpb.OCInterface{ + Interface: "eth1", }, - Weight: 0, }, { - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.3.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth2", + NextHopIp: "192.168.3.42", + Interface: &dpb.OCInterface{ + Interface: "eth2", }, - Weight: 0, }}, }, }, @@ -774,55 +715,49 @@ func TestServer(t *testing.T) { }}, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "2002::/49", - }, + NetworkInstance: "DEFAULT", + Cidr: "2002::/49", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -880,55 +815,49 @@ func TestServer(t *testing.T) { }}, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.10.0.0/16", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.10.0.0/16", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.2.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth1", + NextHopIp: "192.168.2.42", + Interface: &dpb.OCInterface{ + Interface: "eth1", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "2003::/49", - }, + NetworkInstance: "DEFAULT", + Cidr: "2003::/49", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.2.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth1", + NextHopIp: "192.168.2.42", + Interface: &dpb.OCInterface{ + Interface: "eth1", }, - Weight: 0, }}, }, }, @@ -986,19 +915,17 @@ func TestServer(t *testing.T) { }}, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -1124,14 +1051,6 @@ func TestServer(t *testing.T) { } } -func gueHeader(t *testing.T, layers ...gopacket.SerializableLayer) []byte { - buf := gopacket.NewSerializeBuffer() - if err := gopacket.SerializeLayers(buf, gopacket.SerializeOptions{}, layers...); err != nil { - t.Fatalf("failed to serialize GUE headers: %v", err) - } - return buf.Bytes() -} - func TestBGPGUEPolicy(t *testing.T) { routesQuery := programmedRoutesQuery(t) inInterfaces, wantConnectedRoutes := getConnectedIntfSetupVars(t) @@ -1177,37 +1096,33 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -1226,73 +1141,41 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(42, 42, 42, 42), - DstIP: net.IPv4(192, 168, 1, 42), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{42, 42, 42, 42}), - DstIP: net.ParseIP(mapAddressTo6(t, "192.168.1.42")), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{42, 42, 42, 42}, + DstIp: []byte{192, 168, 1, 42}, + DstPort: 8, + IsV6: !v4, }, - }}, + }, }}, }, }, @@ -1304,37 +1187,33 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -1358,55 +1237,49 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -1425,91 +1298,57 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(43, 43, 43, 43), - DstIP: net.IPv4(10, 10, 10, 10), - }, &layers.UDP{ - DstPort: layers.UDPPort(9), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{43, 43, 43, 43}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.10.10")), - }, &layers.UDP{ - DstPort: layers.UDPPort(9), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{43, 43, 43, 43}, + DstIp: []byte{10, 10, 10, 10}, + DstPort: 9, + IsV6: !v4, }, - }}, + }, }}, }, }, @@ -1521,55 +1360,49 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -1593,73 +1426,65 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -1678,145 +1503,81 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(8, 8, 8, 8), - DstIP: net.IPv4(10, 10, 10, 10), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{8, 8, 8, 8}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.10.10")), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{8, 8, 8, 8}, + DstIp: []byte{10, 10, 10, 10}, + DstPort: 8, + IsV6: !v4, }, - }}, + }, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(8, 8, 8, 8), - DstIP: net.IPv4(10, 10, 20, 20), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{8, 8, 8, 8}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.20.20")), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{8, 8, 8, 8}, + DstIp: []byte{10, 10, 20, 20}, + DstPort: 8, + IsV6: !v4, }, - }}, + }, }}, }, }, @@ -1835,145 +1596,81 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(8, 8, 8, 8), - DstIP: net.IPv4(10, 10, 10, 10), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{8, 8, 8, 8}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.10.10")), - }, &layers.UDP{ - DstPort: layers.UDPPort(8), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{8, 8, 8, 8}, + DstIp: []byte{10, 10, 10, 10}, + DstPort: 8, + IsV6: !v4, }, - }}, + }, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(16, 16, 16, 16), - DstIP: net.IPv4(10, 10, 20, 20), - }, &layers.UDP{ - DstPort: layers.UDPPort(16), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{16, 16, 16, 16}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.20.20")), - }, &layers.UDP{ - DstPort: layers.UDPPort(16), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{16, 16, 16, 16}, + DstIp: []byte{10, 10, 20, 20}, + DstPort: 16, + IsV6: !v4, }, - }}, + }, }}, }, }, @@ -1985,109 +1682,73 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(16, 16, 16, 16), - DstIP: net.IPv4(10, 10, 20, 20), - }, &layers.UDP{ - DstPort: layers.UDPPort(16), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{16, 16, 16, 16}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.20.20")), - }, &layers.UDP{ - DstPort: layers.UDPPort(16), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{16, 16, 16, 16}, + DstIp: []byte{10, 10, 20, 20}, + DstPort: 16, + IsV6: !v4, }, - }}, + }, }}, }, }, @@ -2112,154 +1773,95 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(16, 16, 16, 16), - DstIP: net.IPv4(10, 10, 20, 20), - }, &layers.UDP{ - DstPort: layers.UDPPort(16), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{ - Version: 6, - NextHeader: layers.IPProtocolUDP, - SrcIP: mapAddressTo6BytesSlice([4]byte{16, 16, 16, 16}), - DstIP: net.ParseIP(mapAddressTo6(t, "10.10.20.20")), - }, &layers.UDP{ - DstPort: layers.UDPPort(16), - SrcPort: 0, - Length: 34, - }, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{16, 16, 16, 16}, + DstIp: []byte{10, 10, 20, 20}, + DstPort: 16, }, - }}, + }, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "4242::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "4242::/42", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, - PreTransmitActions: []*fwdpb.ActionDesc{{ - ActionType: fwdpb.ActionType_ACTION_TYPE_REPARSE, - Action: &fwdpb.ActionDesc_Reparse{ - Reparse: &fwdpb.ReparseActionDesc{ - HeaderId: fwdpb.PacketHeaderId_PACKET_HEADER_ID_IP4, - FieldIds: []*fwdpb.PacketFieldId{ - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_INPUT}}, - {Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_PORT_OUTPUT}}, - }, - Prepend: gueHeader(t, selectGUEHeaders(t, v4, - &layers.IPv4{ - Version: 4, - IHL: 5, - Protocol: layers.IPProtocolUDP, - SrcIP: net.IPv4(16, 16, 16, 16), - DstIP: net.IPv4(10, 10, 20, 30), - }, &layers.UDP{ - DstPort: layers.UDPPort(32), - SrcPort: 0, - Length: 34, - }, - &layers.IPv6{}, &layers.UDP{}, - )...), - }, + Encap: &dpb.NextHop_Gue{ + Gue: &dpb.GUE{ + SrcIp: []byte{16, 16, 16, 16}, + DstIp: []byte{10, 10, 20, 30}, + DstPort: 32, }, - }}, + }, }}, }, }, @@ -2272,73 +1874,65 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -2351,91 +1945,81 @@ func TestBGPGUEPolicy(t *testing.T) { wantRoutes: func(v4 bool) []*dpb.Route { return []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "20.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "20.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "30.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "30.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "40.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "40.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "4242::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "4242::/42", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, diff --git a/sysrib/static_connected_test.go b/sysrib/static_connected_test.go index c95247cd..7351248b 100644 --- a/sysrib/static_connected_test.go +++ b/sysrib/static_connected_test.go @@ -23,25 +23,25 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/openconfig/lemming/gnmi" - "github.com/openconfig/lemming/gnmi/fakedevice" - "github.com/openconfig/lemming/gnmi/gnmiclient" - "github.com/openconfig/lemming/gnmi/oc" - "github.com/openconfig/lemming/gnmi/oc/ocpath" "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" "google.golang.org/grpc" "google.golang.org/grpc/credentials/local" "google.golang.org/protobuf/testing/protocmp" + "github.com/openconfig/lemming/gnmi" + "github.com/openconfig/lemming/gnmi/fakedevice" + "github.com/openconfig/lemming/gnmi/gnmiclient" + "github.com/openconfig/lemming/gnmi/oc" + "github.com/openconfig/lemming/gnmi/oc/ocpath" + gpb "github.com/openconfig/gnmi/proto/gnmi" + dpb "github.com/openconfig/lemming/proto/dataplane" ) -var ( - staticp = ocpath.Root().NetworkInstance(fakedevice.DefaultNetworkInstance). - Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, fakedevice.StaticRoutingProtocol) -) +var staticp = ocpath.Root().NetworkInstance(fakedevice.DefaultNetworkInstance). + Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, fakedevice.StaticRoutingProtocol) func installStaticRoute(t *testing.T, c *ygnmi.Client, route *oc.NetworkInstance_Protocol_Static) { ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(50*time.Second)) @@ -107,36 +107,27 @@ func TestStaticRouteAndIntfs(t *testing.T) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -179,71 +170,53 @@ func TestStaticRouteAndIntfs(t *testing.T) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: mapAddressTo6(t, "192.168.1.0/24"), - }, + NetworkInstance: "DEFAULT", + Cidr: mapAddressTo6(t, "192.168.1.0/24"), }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: mapAddressTo6(t, "10.0.0.0/8"), - }, + NetworkInstance: "DEFAULT", + Cidr: mapAddressTo6(t, "10.0.0.0/8"), }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: mapAddressTo6(t, "192.168.1.42")}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: mapAddressTo6(t, "192.168.1.42"), + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -257,53 +230,37 @@ func TestStaticRouteAndIntfs(t *testing.T) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: mapAddressTo6(t, "192.168.1.0/24"), - }, + NetworkInstance: "DEFAULT", + Cidr: mapAddressTo6(t, "192.168.1.0/24"), }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: mapAddressTo6(t, "10.0.0.0/8"), - }, + NetworkInstance: "DEFAULT", + Cidr: mapAddressTo6(t, "10.0.0.0/8"), }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: mapAddressTo6(t, "192.168.1.42")}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: mapAddressTo6(t, "192.168.1.42"), + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, @@ -317,36 +274,22 @@ func TestStaticRouteAndIntfs(t *testing.T) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: mapAddressTo6(t, "192.168.1.0/24"), - }, + NetworkInstance: "DEFAULT", + Cidr: mapAddressTo6(t, "192.168.1.0/24"), }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }}, diff --git a/sysrib/zapi_test.go b/sysrib/zapi_test.go index d0c833b5..a992fa72 100644 --- a/sysrib/zapi_test.go +++ b/sysrib/zapi_test.go @@ -38,13 +38,14 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/openconfig/lemming/gnmi" - dpb "github.com/openconfig/lemming/proto/dataplane" - pb "github.com/openconfig/lemming/proto/sysrib" "github.com/openconfig/ygnmi/ygnmi" "github.com/osrg/gobgp/v3/pkg/zebra" "google.golang.org/grpc" "google.golang.org/protobuf/testing/protocmp" + + "github.com/openconfig/lemming/gnmi" + dpb "github.com/openconfig/lemming/proto/dataplane" + pb "github.com/openconfig/lemming/proto/sysrib" ) func TestZServer(t *testing.T) { @@ -131,7 +132,7 @@ func testRouteAddDelete(t *testing.T) { Family: syscall.AF_INET, PrefixLen: 8, // TODO(wenbli): This is probably a bug in GoBGP's zebra library. - //Prefix: net.ParseIP("10.0.0.0"), + // Prefix: net.ParseIP("10.0.0.0"), Prefix: net.ParseIP("0a0a::"), }, Nexthops: []zebra.Nexthop{{ @@ -152,37 +153,28 @@ func testRouteAddDelete(t *testing.T) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }}, @@ -213,72 +205,54 @@ func testRouteAddDelete(t *testing.T) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "4242::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "4242::/42", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "2001::ffff"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "2001::ffff", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "2001::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "2001::/42", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }}, @@ -290,7 +264,7 @@ func testRouteAddDelete(t *testing.T) { Family: syscall.AF_INET, PrefixLen: 8, // TODO(wenbli): This is probably a bug in GoBGP's zebra library. - //Prefix: net.ParseIP("10.0.0.0"), + // Prefix: net.ParseIP("10.0.0.0"), Prefix: net.ParseIP("0a0a::"), }, Nexthops: []zebra.Nexthop{{ @@ -305,54 +279,38 @@ func testRouteAddDelete(t *testing.T) { inDelete: true, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "4242::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "4242::/42", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "2001::ffff"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "2001::ffff", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "2001::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "2001::/42", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }}, @@ -377,36 +335,22 @@ func testRouteAddDelete(t *testing.T) { inDelete: true, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "2001::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "2001::/42", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }}, @@ -535,37 +479,28 @@ func testRouteRedistribution(t *testing.T, routeReadyBeforeDial bool) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "10.0.0.0/8", - }, + NetworkInstance: "DEFAULT", + Cidr: "10.0.0.0/8", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "192.168.1.42"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "192.168.1.42", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "192.168.1.0/24", - }, + NetworkInstance: "DEFAULT", + Cidr: "192.168.1.0/24", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }}, @@ -594,37 +529,28 @@ func testRouteRedistribution(t *testing.T, routeReadyBeforeDial bool) { }, wantRoutes: []*dpb.Route{{ Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "4242::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "4242::/42", }, Hop: &dpb.Route_NextHops{ NextHops: &dpb.NextHopList{ + Weights: []uint64{0}, Hops: []*dpb.NextHop{{ - Ip: &dpb.NextHop_IpStr{IpStr: "2001::ffff"}, - Dev: &dpb.NextHop_Port{ - Port: "eth0", + NextHopIp: "2001::ffff", + Interface: &dpb.OCInterface{ + Interface: "eth0", }, - Weight: 0, }}, }, }, }, { Prefix: &dpb.RoutePrefix{ - VrfId: uint64(0), - Prefix: &dpb.RoutePrefix_Cidr{ - Cidr: "2001::/42", - }, + NetworkInstance: "DEFAULT", + Cidr: "2001::/42", }, - Hop: &dpb.Route_NextHops{ - NextHops: &dpb.NextHopList{ - Hops: []*dpb.NextHop{{ - Dev: &dpb.NextHop_Port{ - Port: "eth0", - }, - Weight: 0, - }}, + Hop: &dpb.Route_Interface{ + Interface: &dpb.OCInterface{ + Interface: "eth0", }, }, }},