diff --git a/cmd/evpn-bridge-port.go b/cmd/evpn-bridge-port.go new file mode 100644 index 0000000..ce53224 --- /dev/null +++ b/cmd/evpn-bridge-port.go @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package cmd implements the CLI commands +package cmd + +import ( + "context" + "log" + "time" + + "github.com/opiproject/godpu/network" + "github.com/spf13/cobra" +) + +// CreateBridgePort creates an Bridge Port an OPI server +func CreateBridgePort() *cobra.Command { + var addr string + var name string + var mac string + var bridgePortType string + var logicalBridges []string + + cmd := &cobra.Command{ + Use: "create-bp", + Short: "Create a bridge port", + Long: "Create a BridgePort with the specified name, MAC address, type, and VLAN IDs", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewBridgePort(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + // grpc call to create the bridge port + bridgePort, err := evpnClient.CreateBridgePort(ctx, name, mac, bridgePortType, logicalBridges) + if err != nil { + log.Fatalf("could not create Bridge Port: %v", err) + } + log.Printf("Created Bridge Port:\n status: %s\n type: %s\n name: %s\n bridges: %s\n mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), + bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().StringVar(&mac, "mac", "", "Specify the MAC address") + cmd.Flags().StringVarP(&bridgePortType, "type", "t", "", "Specify the type (access or trunk)") + cmd.Flags().StringSliceVar(&logicalBridges, "logicalBridges", []string{}, "Specify VLAN IDs (multiple values supported)") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("mac"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + if err := cmd.MarkFlagRequired("type"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + // Define allowed choices for the "type" Flag + err := cmd.RegisterFlagCompletionFunc("type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"access", "trunk"}, cobra.ShellCompDirectiveNoFileComp + }) + if err != nil { + log.Fatalf("Error registering flag completion function: %v", err) + } + return cmd +} + +// DeleteBridgePort delete an Bridge Port an OPI server +func DeleteBridgePort() *cobra.Command { + var addr string + var name string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "delete-bp", + Short: "Delete a bridge port", + Long: "Delete a BridgePort with the specified name", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewBridgePort(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + _, err = evpnClient.DeleteBridgePort(ctx, name, allowMissing) + if err != nil { + log.Fatalf("DeleteBridgePort: Error occurred while deleting Bridge Port: %q", err) + } + log.Printf("Deleted BridgePort ") + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify if missing allowed") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + return cmd +} + +// GetBridgePort Get Bridge Port details +func GetBridgePort() *cobra.Command { + var addr string + var name string + + cmd := &cobra.Command{ + Use: "get-bp", + Short: "Show details of a bridge port", + Long: "Show details of a BridgePort with the specified name", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewBridgePort(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + bridgePort, err := evpnClient.GetBridgePort(ctx, name) + if err != nil { + log.Fatalf("GetBridgePort: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("Bridge Port:\n status: %s\n type: %s\n name: %s\n bridges: %s\n mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), + bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// ListBridgePorts list all the Bridge Port an OPI server +func ListBridgePorts() *cobra.Command { + var addr string + var pageSize int32 + var pageToken string + + cmd := &cobra.Command{ + Use: "list-bps", + Short: "Show details of all bridge ports", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewBridgePort(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + for { + resp, err := evpnClient.ListBridgePorts(ctx, pageSize, pageToken) + if err != nil { + log.Fatalf("Failed to get items: %v", err) + } + // Process the server response + for _, bridgePort := range resp.BridgePorts { + log.Printf("Bridge Port:\n status: %s\n type: %s\n name: %s\n bridges: %s\n mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), + bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) + } + + // Check if there are more pages to retrieve + if resp.NextPageToken == "" { + // No more pages, break the loop + break + } + // Update the page token for the next request + pageToken = resp.NextPageToken + } + }, + } + cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") + cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd +} + +// UpdateBridgePort update the Bridge Port on OPI server +func UpdateBridgePort() *cobra.Command { + var addr string + var name string + var updateMask []string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "update-bp", + Short: "Update the bridge port", + Long: "updates the Bridge Port with updated mask", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewBridgePort(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + bridgePort, err := evpnClient.UpdateBridgePort(ctx, name, updateMask, allowMissing) + if err != nil { + log.Fatalf("UpdateBridgePort: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("Bridge Port:\n status: %s\n type: %s\n name: %s\n bridges: %s\n mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), + bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) + }, + } + cmd.Flags().StringVar(&name, "name", "", "name of the Bridge Port") + cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd +} diff --git a/cmd/evpn-logical-brige.go b/cmd/evpn-logical-brige.go new file mode 100644 index 0000000..bbccda4 --- /dev/null +++ b/cmd/evpn-logical-brige.go @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package cmd implements the CLI commands +package cmd + +import ( + "context" + "log" + "time" + + "github.com/opiproject/godpu/network" + "github.com/spf13/cobra" +) + +// CreateLogicalBridge creates an Logical Bridge an OPI server +func CreateLogicalBridge() *cobra.Command { + var addr string + var name string + var vlanID uint32 + var vni uint32 + + cmd := &cobra.Command{ + Use: "create-lb", + Short: "Create a logical bridge", + Long: "Create a logical bridge with the specified name, VLAN ID, and VNI", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewLogicalBridge(addr) + if err != nil { + log.Fatalf("could create gRPC client: %v", err) + } + defer cancel() + + resp, err := evpnClient.CreateLogicalBridge(ctx, name, vlanID, vni) + if err != nil { + log.Fatalf("failed to create logical bridge: %v", err) + } + + log.Printf(" Created Logical Bridge \n name: %s\n vlan: %d\n vni: %d\n status: %s\n", resp.GetName(), resp.GetSpec().GetVlanId(), + resp.GetSpec().GetVni(), resp.GetStatus()) + }, + } + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the logical bridge") + cmd.Flags().Uint32VarP(&vlanID, "vlan-id", "v", 0, "Specify the VLAN ID") + cmd.Flags().Uint32VarP(&vni, "vni", "i", 0, "Specify the VNI") + + if err := cmd.MarkFlagRequired("addr"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + if err := cmd.MarkFlagRequired("vlan-id"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + if err := cmd.MarkFlagRequired("vni"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + return cmd +} + +// DeleteLogicalBridge deletes an Logical Bridge an OPI server +func DeleteLogicalBridge() *cobra.Command { + var addr string + var name string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "delete-lb", + Short: "Delete a logical bridge", + Long: "Delete a logical bridge with the specified name", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewLogicalBridge(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + resp, err := evpnClient.DeleteLogicalBridge(ctx, name, allowMissing) + if err != nil { + log.Fatalf("failed to delete logical bridge: %v", err) + } + + log.Printf("Deleted Logical Bridge: %s\n", resp) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify allow missing") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// GetLogicalBridge get Logical Bridge details from OPI server +func GetLogicalBridge() *cobra.Command { + var addr string + var name string + + cmd := &cobra.Command{ + Use: "get-lb", + Short: "Show details of a logical bridge", + Long: "Show details of a logical bridge with the specified name", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewLogicalBridge(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + resp, err := evpnClient.GetLogicalBridge(ctx, name) + if err != nil { + log.Fatalf("failed to get logical bridge: %v", err) + } + + log.Printf(" Created Logical Bridge \n name: %s\n vlan: %d\n vni: %d\n status: %s\n", resp.GetName(), resp.GetSpec().GetVlanId(), + resp.GetSpec().GetVni(), resp.GetStatus()) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + return cmd +} + +// ListLogicalBridges list all Logical Bridge details from OPI server +func ListLogicalBridges() *cobra.Command { + var addr string + var pageSize int32 + var pageToken string + cmd := &cobra.Command{ + Use: "list-lbs", + Short: "Show details of all logical bridges", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewLogicalBridge(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + for { + resp, err := evpnClient.ListLogicalBridges(ctx, pageSize, pageToken) + if err != nil { + log.Fatalf("Failed to get items: %v", err) + } + // Process the server response + for _, item := range resp.LogicalBridges { + log.Printf(" Created Logical Bridge \n name: %s\n vlan: %d\n vni: %d\n status: %s\n", item.GetName(), item.GetSpec().GetVlanId(), + item.GetSpec().GetVni(), item.GetStatus()) + } + + // Check if there are more pages to retrieve + if resp.NextPageToken == "" { + // No more pages, break the loop + break + } + // Update the page token for the next request + pageToken = resp.NextPageToken + } + }, + } + + cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") + cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd +} + +// UpdateLogicalBridge update Logical Bridge on OPI server +func UpdateLogicalBridge() *cobra.Command { + var addr string + var name string + var updateMask []string + cmd := &cobra.Command{ + Use: "update-lb", + Short: "update the logical bridge", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewLogicalBridge(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + resp, err := evpnClient.UpdateLogicalBridge(ctx, name, updateMask) + if err != nil { + log.Fatalf("failed to update logical bridge: %v", err) + } + + log.Printf(" Updated Logical Bridge \n name: %s\n vlan: %d\n vni: %d\n status: %s\n", resp.GetName(), resp.GetSpec().GetVlanId(), + resp.GetSpec().GetVni(), resp.GetStatus()) + }, + } + cmd.Flags().StringVar(&name, "name", "", "name of the logical bridge") + cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + return cmd +} diff --git a/cmd/evpn-svi.go b/cmd/evpn-svi.go new file mode 100644 index 0000000..c12e381 --- /dev/null +++ b/cmd/evpn-svi.go @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package cmd implements the CLI commands +package cmd + +import ( + "context" + "log" + "time" + + "github.com/opiproject/godpu/network" + "github.com/spf13/cobra" +) + +// CreateSVI create svi on OPI server +func CreateSVI() *cobra.Command { + var addr string + var name string + var vrf string + var logicalBridge string + var mac string + var gwIPs []string + var ebgp bool + var remoteAS uint32 + + cmd := &cobra.Command{ + Use: "create-svi", + Short: "Create a SVI", + Long: "Create an using name, vrf,logical bridges, mac, gateway ip's and enable bgp ", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewSVI(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + svi, err := evpnClient.CreateSvi(ctx, name, vrf, logicalBridge, mac, gwIPs, ebgp, remoteAS) + if err != nil { + log.Fatalf("failed to create logical bridge: %v", err) + } + + log.Printf("CreateSVI: Created SVI \n name: %s\n status: %d\n Vrf: %s\n LogicalBridge: %s\n MacAddress: %s\n EnableBgp: %t\n GwIPs: %s\nremoteAS: %d\n", + svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), + svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) + }, + } + cmd.Flags().StringVar(&vrf, "vrf", "", "Must be unique") + cmd.Flags().StringVar(&logicalBridge, "logicalBridge", "", "Pair of vni and vlan_id must be unique") + cmd.Flags().StringVar(&mac, "mac", "", "GW MAC address, random MAC assigned if not specified") + cmd.Flags().StringSliceVar(&gwIPs, "gw-ips", nil, "List of GW IP addresses") + cmd.Flags().BoolVar(&ebgp, "ebgp", false, "Enable eBGP in VRF for tenants connected through this SVI") + cmd.Flags().Uint32VarP(&remoteAS, "remote-as", "", 0, "The remote AS") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("vrf"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + if err := cmd.MarkFlagRequired("logicalBridge"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + if err := cmd.MarkFlagRequired("mac"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + if err := cmd.MarkFlagRequired("gw-ips"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// DeleteSVI delete the svi on OPI server +func DeleteSVI() *cobra.Command { + var addr string + var name string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "delete-svi", + Short: "Delete a SVI", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewSVI(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + _, err = evpnClient.DeleteSvi(ctx, name, allowMissing) + if err != nil { + log.Fatalf("failed to create logical bridge: %v", err) + } + + log.Printf("Deleted SVI ") + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// GetSVI get svi details from OPI server +func GetSVI() *cobra.Command { + var addr string + var name string + + cmd := &cobra.Command{ + Use: "get-svi", + Short: "Show details of a SVI", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewSVI(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + svi, err := evpnClient.GetSvi(ctx, name) + if err != nil { + log.Fatalf("GetSVI: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("GetSVI: Created SVI \n name: %s\n status: %d\n Vrf: %s\n LogicalBridge: %s\n MacAddress: %s\n EnableBgp: %t\n GwIPs: %s\nremoteAS: %d\n", + svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), + svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// ListSVIs get all the svi's from OPI server +func ListSVIs() *cobra.Command { + var addr string + var pageSize int32 + var pageToken string + + cmd := &cobra.Command{ + Use: "list-svis", + Short: "Show details of all SVIs", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewSVI(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + for { + resp, err := evpnClient.ListSvis(ctx, pageSize, pageToken) + if err != nil { + log.Fatalf("Failed to get items: %v", err) + } + // Process the server response + for _, svi := range resp.Svis { + log.Printf("ListSVIs: SVI \n name: %s\n status: %d\n Vrf: %s\n LogicalBridge: %s\n MacAddress: %s\n EnableBgp: %t\n GwIPs: %s\nremoteAS: %d\n", + svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), + svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) + } + + // Check if there are more pages to retrieve + if resp.NextPageToken == "" { + // No more pages, break the loop + break + } + // Update the page token for the next request + pageToken = resp.NextPageToken + } + }, + } + + cmd.Flags().Int32VarP(&pageSize, "pageSize", "s", 0, "Specify the name of the BridgePort") + cmd.Flags().StringVarP(&pageToken, "pageToken", "p", "", "Specify the page token") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd +} + +// UpdateSVI update the svi on OPI server +func UpdateSVI() *cobra.Command { + var addr string + var name string + var updateMask []string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "update-svi", + Short: "update the SVI", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewSVI(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + svi, err := evpnClient.UpdateSvi(ctx, name, updateMask, allowMissing) + if err != nil { + log.Fatalf("GetBridgePort: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("UpdateSVI: SVI \n name: %s\n status: %d\n Vrf: %s\n LogicalBridge: %s\n MacAddress: %s\n EnableBgp: %t\n GwIPs: %s\nremoteAS: %d\n", + svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), + svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) + }, + } + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") + return cmd +} diff --git a/cmd/evpn-test.go b/cmd/evpn-test.go index 80da251..9446c92 100644 --- a/cmd/evpn-test.go +++ b/cmd/evpn-test.go @@ -1,815 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. // Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. // Package cmd implements the CLI commands package cmd import ( - "context" "log" - "time" - "github.com/opiproject/godpu/network" "github.com/spf13/cobra" ) -// CreateLogicalBridge creates an Logical Bridge an OPI server -func CreateLogicalBridge() *cobra.Command { - var addr string - var name string - var vlanID uint32 - var vni uint32 - - cmd := &cobra.Command{ - Use: "create-lb", - Short: "Create a logical bridge", - Long: "Create a logical bridge with the specified name, VLAN ID, and VNI", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) - if err != nil { - log.Fatalf("could create gRPC client: %v", err) - } - defer cancel() - - resp, err := evpnClient.CreateLogicalBridge(ctx, name, vlanID, vni) - if err != nil { - log.Fatalf("failed to create logical bridge: %v", err) - } - - log.Printf(" Created Logical Bridge \n name: %s,\n vlan: %d,\n vni: %d,\n status: %s\n", resp.GetName(), resp.GetSpec().GetVlanId(), - resp.GetSpec().GetVni(), resp.GetStatus()) - }, - } - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the logical bridge") - cmd.Flags().Uint32VarP(&vlanID, "vlan-id", "v", 0, "Specify the VLAN ID") - cmd.Flags().Uint32VarP(&vni, "vni", "i", 0, "Specify the VNI") - - if err := cmd.MarkFlagRequired("addr"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - if err := cmd.MarkFlagRequired("vlan-id"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - if err := cmd.MarkFlagRequired("vni"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - return cmd -} - -// DeleteLogicalBridge deletes an Logical Bridge an OPI server -func DeleteLogicalBridge() *cobra.Command { - var addr string - var name string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "delete-lb", - Short: "Delete a logical bridge", - Long: "Delete a logical bridge with the specified name", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - resp, err := evpnClient.DeleteLogicalBridge(ctx, name, allowMissing) - if err != nil { - log.Fatalf("failed to delete logical bridge: %v", err) - } - - log.Printf("Deleted Logical Bridge: %s\n", resp) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify allow missing") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// GetLogicalBridge get Logical Bridge details from OPI server -func GetLogicalBridge() *cobra.Command { - var addr string - var name string - - cmd := &cobra.Command{ - Use: "get-lb", - Short: "Show details of a logical bridge", - Long: "Show details of a logical bridge with the specified name", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - resp, err := evpnClient.GetLogicalBridge(ctx, name) - if err != nil { - log.Fatalf("failed to get logical bridge: %v", err) - } - - log.Printf(" Created Logical Bridge \n name: %s,\n vlan: %d,\n vni: %d,\n status: %s\n", resp.GetName(), resp.GetSpec().GetVlanId(), - resp.GetSpec().GetVni(), resp.GetStatus()) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - return cmd -} - -// ListLogicalBridges list all Logical Bridge details from OPI server -func ListLogicalBridges() *cobra.Command { - var addr string - var pageSize int32 - var pageToken string - cmd := &cobra.Command{ - Use: "list-lbs", - Short: "Show details of all logical bridges", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - for { - resp, err := evpnClient.ListLogicalBridges(ctx, pageSize, pageToken) - if err != nil { - log.Fatalf("Failed to get items: %v", err) - } - // Process the server response - for _, item := range resp.LogicalBridges { - log.Printf(" Created Logical Bridge \n name: %s,\n vlan: %d,\n vni: %d,\n status: %s\n", item.GetName(), item.GetSpec().GetVlanId(), - item.GetSpec().GetVni(), item.GetStatus()) - } - - // Check if there are more pages to retrieve - if resp.NextPageToken == "" { - // No more pages, break the loop - break - } - // Update the page token for the next request - pageToken = resp.NextPageToken - } - }, - } - - cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") - cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - return cmd -} - -// UpdateLogicalBridge update Logical Bridge on OPI server -func UpdateLogicalBridge() *cobra.Command { - var addr string - var name string - var updateMask []string - cmd := &cobra.Command{ - Use: "update-lb", - Short: "update the logical bridge", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - resp, err := evpnClient.UpdateLogicalBridge(ctx, name, updateMask) - if err != nil { - log.Fatalf("failed to update logical bridge: %v", err) - } - - log.Printf(" Updated Logical Bridge \n name: %s,\n vlan: %d,\n vni: %d,\n status: %s\n", resp.GetName(), resp.GetSpec().GetVlanId(), - resp.GetSpec().GetVni(), resp.GetStatus()) - }, - } - cmd.Flags().StringVar(&name, "name", "", "name of the logical bridge") - cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - return cmd -} - -// CreateBridgePort creates an Bridge Port an OPI server -func CreateBridgePort() *cobra.Command { - var addr string - var name string - var mac string - var bridgePortType string - var logicalBridges []string - - cmd := &cobra.Command{ - Use: "create-bp", - Short: "Create a bridge port", - Long: "Create a BridgePort with the specified name, MAC address, type, and VLAN IDs", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - // grpc call to create the bridge port - bridgePort, err := evpnClient.CreateBridgePort(ctx, name, mac, bridgePortType, logicalBridges) - if err != nil { - log.Fatalf("could not create Bridge Port: %v", err) - } - log.Printf("Created Bridge Port:\n status: %s\n, type: %s\n, name: %s\n, bridges: %s\n, mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), - bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&mac, "mac", "", "Specify the MAC address") - cmd.Flags().StringVarP(&bridgePortType, "type", "t", "", "Specify the type (access or trunk)") - cmd.Flags().StringSliceVar(&logicalBridges, "logicalBridges", []string{}, "Specify VLAN IDs (multiple values supported)") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("mac"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - if err := cmd.MarkFlagRequired("type"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - // Define allowed choices for the "type" Flag - err := cmd.RegisterFlagCompletionFunc("type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"access", "trunk"}, cobra.ShellCompDirectiveNoFileComp - }) - if err != nil { - log.Fatalf("Error registering flag completion function: %v", err) - } - return cmd -} - -// DeleteBridgePort delete an Bridge Port an OPI server -func DeleteBridgePort() *cobra.Command { - var addr string - var name string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "delete-bp", - Short: "Delete a bridge port", - Long: "Delete a BridgePort with the specified name", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - _, err = evpnClient.DeleteBridgePort(ctx, name, allowMissing) - if err != nil { - log.Fatalf("DeleteBridgePort: Error occurred while deleting Bridge Port: %q", err) - } - log.Printf("Deleted BridgePort ") - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify if missing allowed") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - return cmd -} - -// GetBridgePort Get Bridge Port details -func GetBridgePort() *cobra.Command { - var addr string - var name string - - cmd := &cobra.Command{ - Use: "get-bp", - Short: "Show details of a bridge port", - Long: "Show details of a BridgePort with the specified name", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - bridgePort, err := evpnClient.GetBridgePort(ctx, name) - if err != nil { - log.Fatalf("GetBridgePort: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("Bridge Port:\n status: %s\n, type: %s\n, name: %s\n, bridges: %s\n, mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), - bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// ListBridgePorts list all the Bridge Port an OPI server -func ListBridgePorts() *cobra.Command { - var addr string - var pageSize int32 - var pageToken string - - cmd := &cobra.Command{ - Use: "list-bps", - Short: "Show details of all bridge ports", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - for { - resp, err := evpnClient.ListBridgePorts(ctx, pageSize, pageToken) - if err != nil { - log.Fatalf("Failed to get items: %v", err) - } - // Process the server response - for _, bridgePort := range resp.BridgePorts { - log.Printf("Bridge Port:\n status: %s\n, type: %s\n, name: %s\n, bridges: %s\n, mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), - bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) - } - - // Check if there are more pages to retrieve - if resp.NextPageToken == "" { - // No more pages, break the loop - break - } - // Update the page token for the next request - pageToken = resp.NextPageToken - } - }, - } - cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") - cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - return cmd -} - -// UpdateBridgePort update the Bridge Port on OPI server -func UpdateBridgePort() *cobra.Command { - var addr string - var name string - var updateMask []string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "update-bp", - Short: "Update the bridge port", - Long: "updates the Bridge Port with updated mask", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - bridgePort, err := evpnClient.UpdateBridgePort(ctx, name, updateMask, allowMissing) - if err != nil { - log.Fatalf("UpdateBridgePort: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("Bridge Port:\n status: %s\n, type: %s\n, name: %s\n, bridges: %s\n, mac: %s\n", bridgePort.GetStatus().GetOperStatus(), bridgePort.GetSpec().GetPtype(), - bridgePort.GetName(), bridgePort.GetSpec().GetLogicalBridges(), bridgePort.GetSpec().GetMacAddress()) - }, - } - cmd.Flags().StringVar(&name, "name", "", "name of the Bridge Port") - cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - return cmd -} - -// CreateVRF Create vrf on OPI Server -func CreateVRF() *cobra.Command { - var addr string - var name string - var vni uint32 - var loopback string - var vtep string - - cmd := &cobra.Command{ - Use: "create-vrf", - Short: "Create a VRF", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - vrf, err := evpnClient.CreateVrf(ctx, name, vni, loopback, vtep) - if err != nil { - log.Fatalf("failed to create logical bridge: %v", err) - } - log.Printf("Created VRF with name: %s\n, vni : %d\n, vtep ip : %s\n, loopback ip: %s\n", vrf.GetName(), vrf.GetSpec().GetVni(), - vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Descriptive name") - cmd.Flags().Uint32VarP(&vni, "vni", "v", 0, "Must be unique ") - cmd.Flags().StringVar(&loopback, "loopback", "", "Loopback IP address") - cmd.Flags().StringVar(&vtep, "vtep", "", "VTEP IP address") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("vni"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - if err := cmd.MarkFlagRequired("loopback"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// DeleteVRF update the vrf on OPI server -func DeleteVRF() *cobra.Command { - var addr string - var name string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "delete-vrf", - Short: "Delete a VRF", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - _, err = evpnClient.DeleteVrf(ctx, name, allowMissing) - if err != nil { - log.Fatalf("DeleteVRF: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("Deleted VRF with VPort ID: %s\n", name) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - return cmd -} - -// GetVRF get vrf details from OPI server -func GetVRF() *cobra.Command { - var addr string - var name string - - cmd := &cobra.Command{ - Use: "get-vrf", - Short: "Show details of a VRF", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - vrf, err := evpnClient.GetVrf(ctx, name) - if err != nil { - log.Fatalf("DeleteVRF: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("VRF with name: %s\n, operation status: %d\n,vni : %d\n, vtep ip : %s\n, loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), - vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// ListVRFs list all vrf's with details from OPI server -func ListVRFs() *cobra.Command { - var addr string - var pageSize int32 - var pageToken string - - cmd := &cobra.Command{ - Use: "list-vrfs", - Short: "Show details of all Vrfs", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - for { - resp, err := evpnClient.ListVrfs(ctx, pageSize, pageToken) - if err != nil { - log.Fatalf("Failed to get items: %v", err) - } - // Process the server response - for _, vrf := range resp.Vrfs { - log.Printf("VRF with name: %s\n, operation status: %d\n,vni : %d\n, vtep ip : %s\n, loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), - vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) - } - - // Check if there are more pages to retrieve - if resp.NextPageToken == "" { - // No more pages, break the loop - break - } - // Update the page token for the next request - pageToken = resp.NextPageToken - } - }, - } - cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") - cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - return cmd -} - -// UpdateVRF update the vrf on OPI server -func UpdateVRF() *cobra.Command { - var addr string - var name string - var updateMask []string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "update-vrf", - Short: "update the VRF", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - vrf, err := evpnClient.UpdateVrf(ctx, name, updateMask, allowMissing) - if err != nil { - log.Fatalf("GetBridgePort: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("Updated VRF with name: %s\n, operation status: %d\n,vni : %d\n, vtep ip : %s\n, loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), - vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) - }, - } - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") - cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") - - return cmd -} - -// CreateSVI create svi on OPI server -func CreateSVI() *cobra.Command { - var addr string - var name string - var vrf string - var logicalBridge string - var mac string - var gwIPs []string - var ebgp bool - var remoteAS uint32 - - cmd := &cobra.Command{ - Use: "create-svi", - Short: "Create a SVI", - Long: "Create an using name, vrf,logical bridges, mac, gateway ip's and enable bgp ", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - svi, err := evpnClient.CreateSvi(ctx, name, vrf, logicalBridge, mac, gwIPs, ebgp, remoteAS) - if err != nil { - log.Fatalf("failed to create logical bridge: %v", err) - } - - log.Printf("CreateSVI: Created SVI \n name: %s,\n status: %d,\n Vrf: %s,\n LogicalBridge: %s,\n MacAddress: %s,\n EnableBgp: %t,\n GwIPs: %s,\nremoteAS: %d\n", - svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), - svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) - }, - } - cmd.Flags().StringVar(&vrf, "vrf", "", "Must be unique") - cmd.Flags().StringVar(&logicalBridge, "logicalBridge", "", "Pair of vni and vlan_id must be unique") - cmd.Flags().StringVar(&mac, "mac", "", "GW MAC address, random MAC assigned if not specified") - cmd.Flags().StringSliceVar(&gwIPs, "gw-ips", nil, "List of GW IP addresses") - cmd.Flags().BoolVar(&ebgp, "ebgp", false, "Enable eBGP in VRF for tenants connected through this SVI") - cmd.Flags().Uint32VarP(&remoteAS, "remote-as", "", 0, "The remote AS") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("vrf"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - if err := cmd.MarkFlagRequired("logicalBridge"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - if err := cmd.MarkFlagRequired("mac"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - - if err := cmd.MarkFlagRequired("gw-ips"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// DeleteSVI delete the svi on OPI server -func DeleteSVI() *cobra.Command { - var addr string - var name string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "delete-svi", - Short: "Delete a SVI", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - _, err = evpnClient.DeleteSvi(ctx, name, allowMissing) - if err != nil { - log.Fatalf("failed to create logical bridge: %v", err) - } - - log.Printf("Deleted SVI ") - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// GetSVI get svi details from OPI server -func GetSVI() *cobra.Command { - var addr string - var name string - - cmd := &cobra.Command{ - Use: "get-svi", - Short: "Show details of a SVI", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - svi, err := evpnClient.GetSvi(ctx, name) - if err != nil { - log.Fatalf("GetSVI: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("GetSVI: Created SVI \n name: %s,\n status: %d,\n Vrf: %s,\n LogicalBridge: %s,\n MacAddress: %s,\n EnableBgp: %t,\n GwIPs: %s,\nremoteAS: %d\n", - svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), - svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) - }, - } - - cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - - if err := cmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } - return cmd -} - -// ListSVIs get all the svi's from OPI server -func ListSVIs() *cobra.Command { - var addr string - var pageSize int32 - var pageToken string - - cmd := &cobra.Command{ - Use: "list-svis", - Short: "Show details of all SVIs", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - for { - resp, err := evpnClient.ListSvis(ctx, pageSize, pageToken) - if err != nil { - log.Fatalf("Failed to get items: %v", err) - } - // Process the server response - for _, svi := range resp.Svis { - log.Printf("ListSVIs: SVI \n name: %s,\n status: %d,\n Vrf: %s,\n LogicalBridge: %s,\n MacAddress: %s,\n EnableBgp: %t,\n GwIPs: %s,\nremoteAS: %d\n", - svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), - svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) - } - - // Check if there are more pages to retrieve - if resp.NextPageToken == "" { - // No more pages, break the loop - break - } - // Update the page token for the next request - pageToken = resp.NextPageToken - } - }, - } - - cmd.Flags().Int32VarP(&pageSize, "pageSize", "s", 0, "Specify the name of the BridgePort") - cmd.Flags().StringVarP(&pageToken, "pageToken", "p", "", "Specify the page token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - return cmd -} - -// UpdateSVI update the svi on OPI server -func UpdateSVI() *cobra.Command { - var addr string - var name string - var updateMask []string - var allowMissing bool - - cmd := &cobra.Command{ - Use: "update-svi", - Short: "update the SVI", - Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) - if err != nil { - log.Fatalf("could not create gRPC client: %v", err) - } - defer cancel() - - // grpc call to create the bridge port - svi, err := evpnClient.UpdateSvi(ctx, name, updateMask, allowMissing) - if err != nil { - log.Fatalf("GetBridgePort: Error occurred while creating Bridge Port: %q", err) - } - log.Printf("UpdateSVI: SVI \n name: %s,\n status: %d,\n Vrf: %s,\n LogicalBridge: %s,\n MacAddress: %s,\n EnableBgp: %t,\n GwIPs: %s,\nremoteAS: %d\n", - svi.GetName(), svi.GetStatus().GetOperStatus(), svi.GetSpec().GetVrf(), svi.GetSpec().GetLogicalBridge(), svi.GetSpec().GetMacAddress(), - svi.GetSpec().GetEnableBgp(), svi.GetSpec().GetGwIpPrefix(), svi.GetSpec().GetRemoteAs()) - }, - } - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") - cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") - return cmd -} - // NewEvpnCommand tests the EVPN functionality command func NewEvpnCommand() *cobra.Command { cmd := &cobra.Command{ diff --git a/cmd/evpn-vrf.go b/cmd/evpn-vrf.go new file mode 100644 index 0000000..4302de0 --- /dev/null +++ b/cmd/evpn-vrf.go @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package cmd implements the CLI commands +package cmd + +import ( + "context" + "log" + "time" + + "github.com/opiproject/godpu/network" + "github.com/spf13/cobra" +) + +// CreateVRF Create vrf on OPI Server +func CreateVRF() *cobra.Command { + var addr string + var name string + var vni uint32 + var loopback string + var vtep string + + cmd := &cobra.Command{ + Use: "create-vrf", + Short: "Create a VRF", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewVRF(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + vrf, err := evpnClient.CreateVrf(ctx, name, vni, loopback, vtep) + if err != nil { + log.Fatalf("failed to create logical bridge: %v", err) + } + log.Printf("Created VRF with \n name: %s\n operation status: %d\n vni : %d\n vtep ip : %s\n loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), + vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Descriptive name") + cmd.Flags().Uint32VarP(&vni, "vni", "v", 0, "Must be unique ") + cmd.Flags().StringVar(&loopback, "loopback", "", "Loopback IP address") + cmd.Flags().StringVar(&vtep, "vtep", "", "VTEP IP address") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("vni"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + + if err := cmd.MarkFlagRequired("loopback"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// DeleteVRF update the vrf on OPI server +func DeleteVRF() *cobra.Command { + var addr string + var name string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "delete-vrf", + Short: "Delete a VRF", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewVRF(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + _, err = evpnClient.DeleteVrf(ctx, name, allowMissing) + if err != nil { + log.Fatalf("DeleteVRF: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("Deleted VRF with VPort ID: %s\n", name) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + return cmd +} + +// GetVRF get vrf details from OPI server +func GetVRF() *cobra.Command { + var addr string + var name string + + cmd := &cobra.Command{ + Use: "get-vrf", + Short: "Show details of a VRF", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewVRF(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + vrf, err := evpnClient.GetVrf(ctx, name) + if err != nil { + log.Fatalf("DeleteVRF: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("VRF with \n name: %s\n operation status: %d\n vni : %d\n vtep ip : %s\n loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), + vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) + }, + } + + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + + if err := cmd.MarkFlagRequired("name"); err != nil { + log.Fatalf("Error marking flag as required: %v", err) + } + return cmd +} + +// ListVRFs list all vrf's with details from OPI server +func ListVRFs() *cobra.Command { + var addr string + var pageSize int32 + var pageToken string + + cmd := &cobra.Command{ + Use: "list-vrfs", + Short: "Show details of all Vrfs", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewVRF(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + for { + resp, err := evpnClient.ListVrfs(ctx, pageSize, pageToken) + if err != nil { + log.Fatalf("Failed to get items: %v", err) + } + // Process the server response + for _, vrf := range resp.Vrfs { + log.Printf("VRF with \n name: %s\n operation status: %d\n vni : %d\n vtep ip : %s\n loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), + vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) + } + + // Check if there are more pages to retrieve + if resp.NextPageToken == "" { + // No more pages, break the loop + break + } + // Update the page token for the next request + pageToken = resp.NextPageToken + } + }, + } + cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") + cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd +} + +// UpdateVRF update the vrf on OPI server +func UpdateVRF() *cobra.Command { + var addr string + var name string + var updateMask []string + var allowMissing bool + + cmd := &cobra.Command{ + Use: "update-vrf", + Short: "update the VRF", + Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + evpnClient, err := network.NewVRF(addr) + if err != nil { + log.Fatalf("could not create gRPC client: %v", err) + } + defer cancel() + + // grpc call to create the bridge port + vrf, err := evpnClient.UpdateVrf(ctx, name, updateMask, allowMissing) + if err != nil { + log.Fatalf("GetBridgePort: Error occurred while creating Bridge Port: %q", err) + } + log.Printf("Updated VRF with \n name: %s\n operation status: %d\n vni : %d\n vtep ip : %s\n loopback ip: %s\n", vrf.GetName(), vrf.GetStatus().GetOperStatus(), + vrf.GetSpec().GetVni(), vrf.GetSpec().GetVtepIpPrefix(), vrf.GetSpec().GetLoopbackIpPrefix()) + }, + } + cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") + cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") + cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") + + return cmd +} diff --git a/network/bridge_port.go b/network/bridge_port.go new file mode 100644 index 0000000..dae9a80 --- /dev/null +++ b/network/bridge_port.go @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network + +import ( + "context" + "log" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" + "google.golang.org/protobuf/types/known/emptypb" + "google.golang.org/protobuf/types/known/fieldmaskpb" +) + +// CreateBridgePort creates an Bridge Port an OPI server +func (c evpnClientImpl) CreateBridgePort(ctx context.Context, name string, mac string, bridgePortType string, logicalBridges []string) (*pb.BridgePort, error) { + var typeOfPort pb.BridgePortType + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnBridgePortClient(conn) + switch bridgePortType { + case "access": + typeOfPort = pb.BridgePortType_ACCESS + case "trunk": + typeOfPort = pb.BridgePortType_TRUNK + default: + typeOfPort = pb.BridgePortType_UNKNOWN + } + data, err := client.CreateBridgePort(ctx, &pb.CreateBridgePortRequest{ + BridgePortId: name, + BridgePort: &pb.BridgePort{ + Spec: &pb.BridgePortSpec{ + MacAddress: []byte(mac), + Ptype: typeOfPort, + LogicalBridges: logicalBridges, + }, + }, + }) + if err != nil { + log.Printf("error creating Bridge Port: %s\n", err) + return nil, err + } + + return data, nil +} + +// DeleteBridgePort delete an Bridge Port an OPI server +func (c evpnClientImpl) DeleteBridgePort(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnBridgePortClient(conn) + data, err := client.DeleteBridgePort(ctx, &pb.DeleteBridgePortRequest{ + Name: resourceIDToFullName("ports", name), + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error deleting Bridge Port: %s\n", err) + return nil, err + } + + return data, nil +} + +// GetBridgePort Get Bridge Port details +func (c evpnClientImpl) GetBridgePort(ctx context.Context, name string) (*pb.BridgePort, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnBridgePortClient(conn) + data, err := client.GetBridgePort(ctx, &pb.GetBridgePortRequest{ + Name: resourceIDToFullName("ports", name), + }) + if err != nil { + log.Printf("error getting Bridge Port: %s\n", err) + return nil, err + } + + return data, nil +} + +// ListBridgePorts list all the Bridge Port an OPI server +func (c evpnClientImpl) ListBridgePorts(ctx context.Context, pageSize int32, pageToken string) (*pb.ListBridgePortsResponse, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnBridgePortClient(conn) + data, err := client.ListBridgePorts(ctx, &pb.ListBridgePortsRequest{ + PageSize: pageSize, + PageToken: pageToken, + }) + if err != nil { + log.Printf("error list Bridge Port: %s\n", err) + return nil, err + } + + return data, nil +} + +// UpdateBridgePort update the Bridge Port on OPI server +func (c evpnClientImpl) UpdateBridgePort(ctx context.Context, name string, updateMask []string, allowMissing bool) (*pb.BridgePort, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnBridgePortClient(conn) + Port := &pb.BridgePort{ + Name: resourceIDToFullName("ports", name), + } + data, err := client.UpdateBridgePort(ctx, &pb.UpdateBridgePortRequest{ + BridgePort: Port, + UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error updating Bridge Port: %s\n", err) + return nil, err + } + + return data, nil +} diff --git a/network/bridge_port_test.go b/network/bridge_port_test.go new file mode 100644 index 0000000..eaee0dd --- /dev/null +++ b/network/bridge_port_test.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network diff --git a/network/evpn.go b/network/evpn.go index 2ee031b..9fba817 100644 --- a/network/evpn.go +++ b/network/evpn.go @@ -1,4 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. // Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. // Package network implements the go library for OPI to be used to establish networking @@ -8,17 +9,11 @@ import ( "context" "errors" "fmt" - "log" - "net" - "strconv" - "strings" grpcOpi "github.com/opiproject/godpu/grpc" pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" - pc "github.com/opiproject/opi-api/network/opinetcommon/v1alpha1/gen/go" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/emptypb" - "google.golang.org/protobuf/types/known/fieldmaskpb" ) // PbEvpnLogicalBridgeClientGetter defines the function type used to retrieve an evpn protobuf LogicalBridgeServiceClient @@ -193,581 +188,3 @@ func NewSVIWithArgs(c grpcOpi.Connector, getter PbEvpnSVIClientGetter) (EvpnClie Connector: c, }, nil } - -// utils - -// Function to convert IPv4 address from net.IP to uint32 -func ip4ToInt(ip net.IP) uint32 { - return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3]) -} - -// Function to parse IP address and prefix from a string of the form "IP/PREFIX" -func parseIPAndPrefix(ipPrefixStr string) (*pc.IPPrefix, error) { - parts := strings.Split(ipPrefixStr, "/") - if len(parts) != 2 { - return nil, fmt.Errorf("invalid IP address with prefix: %s", ipPrefixStr) - } - - ipAddress := parts[0] - prefixLength64, err := strconv.ParseInt(parts[1], 10, 32) - - if err != nil { - return nil, fmt.Errorf("failed to parse prefix length: %s", err) - } - - prefixLength := int32(prefixLength64) - - ip := net.ParseIP(ipAddress) - if ip == nil { - return nil, fmt.Errorf("invalid IP address: %s", ipAddress) - } - - addressFamily := int32(0) - var ipv4Addr uint32 - var ipv6Addr []byte - var addr *pc.IPAddress - if ip.To4() != nil { - addressFamily = 1 // IPv4 - ipv4Addr = ip4ToInt(ip.To4()) - addr = &pc.IPAddress{ - Af: pc.IpAf(addressFamily), - V4OrV6: &pc.IPAddress_V4Addr{ - V4Addr: ipv4Addr, - }, - } - } else { - addressFamily = 2 // IPv6 - ipv6Addr = ip.To16() - addr = &pc.IPAddress{ - Af: pc.IpAf(addressFamily), - V4OrV6: &pc.IPAddress_V6Addr{ - V6Addr: ipv6Addr, - }, - } - } - return &pc.IPPrefix{ - Addr: addr, - Len: prefixLength, - }, nil -} - -// Function to parse an array of IP prefixes from strings to pb.IPPrefix messages -func parseIPPrefixes(ipPrefixesStr []string) ([]*pc.IPPrefix, error) { - const maxPrefixes = 10 // Update this to your expected maximum number of prefixes - var ipPrefixes = make([]*pc.IPPrefix, 0, maxPrefixes) - - for _, ipPrefixStr := range ipPrefixesStr { - ipPrefix, err := parseIPAndPrefix(ipPrefixStr) - if err != nil { - return nil, fmt.Errorf("failed to parse IP prefix: %v", err) - } - ipPrefixes = append(ipPrefixes, ipPrefix) - } - return ipPrefixes, nil -} - -// CreateLogicalBridge creates an Logical Bridge an OPI server -func (c evpnClientImpl) CreateLogicalBridge(ctx context.Context, name string, vlanID uint32, vni uint32) (*pb.LogicalBridge, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnLogicalBridgeClient(conn) - - data, err := client.CreateLogicalBridge(ctx, &pb.CreateLogicalBridgeRequest{ - LogicalBridgeId: name, - LogicalBridge: &pb.LogicalBridge{ - Spec: &pb.LogicalBridgeSpec{ - VlanId: vlanID, - Vni: vni, - }, - }, - }) - if err != nil { - log.Printf("error creating logical bridge: %s\n", err) - return nil, err - } - - return data, nil -} - -// DeleteLogicalBridge deletes an Logical Bridge an OPI server -func (c evpnClientImpl) DeleteLogicalBridge(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnLogicalBridgeClient(conn) - - data, err := client.DeleteLogicalBridge(ctx, &pb.DeleteLogicalBridgeRequest{ - Name: resourceIDToFullName("bridges", name), - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error deleting logical bridge: %s\n", err) - return nil, err - } - - return data, nil -} - -// GetLogicalBridge get Logical Bridge details from OPI server -func (c evpnClientImpl) GetLogicalBridge(ctx context.Context, name string) (*pb.LogicalBridge, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnLogicalBridgeClient(conn) - - data, err := client.GetLogicalBridge(ctx, &pb.GetLogicalBridgeRequest{ - Name: resourceIDToFullName("bridges", name), - }) - if err != nil { - log.Printf("error getting logical bridge: %s\n", err) - return nil, err - } - - return data, nil -} - -// ListLogicalBridges list all Logical Bridge details from OPI server -func (c evpnClientImpl) ListLogicalBridges(ctx context.Context, pageSize int32, pageToken string) (*pb.ListLogicalBridgesResponse, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnLogicalBridgeClient(conn) - - data, err := client.ListLogicalBridges(ctx, &pb.ListLogicalBridgesRequest{ - PageSize: pageSize, - PageToken: pageToken, - }) - if err != nil { - log.Printf("error List logical bridge: %s\n", err) - return nil, err - } - - return data, nil -} - -// UpdateLogicalBridge update Logical Bridge on OPI server -func (c evpnClientImpl) UpdateLogicalBridge(ctx context.Context, name string, updateMask []string) (*pb.LogicalBridge, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnLogicalBridgeClient(conn) - Bridge := &pb.LogicalBridge{ - Name: resourceIDToFullName("bridges", name), - } - data, err := client.UpdateLogicalBridge(ctx, &pb.UpdateLogicalBridgeRequest{ - LogicalBridge: Bridge, - UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, - }) - if err != nil { - log.Printf("error Update logical bridge: %s\n", err) - return nil, err - } - - return data, nil -} - -// CreateBridgePort creates an Bridge Port an OPI server -func (c evpnClientImpl) CreateBridgePort(ctx context.Context, name string, mac string, bridgePortType string, logicalBridges []string) (*pb.BridgePort, error) { - var typeOfPort pb.BridgePortType - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnBridgePortClient(conn) - switch bridgePortType { - case "access": - typeOfPort = pb.BridgePortType_ACCESS - case "trunk": - typeOfPort = pb.BridgePortType_TRUNK - default: - typeOfPort = pb.BridgePortType_UNKNOWN - } - data, err := client.CreateBridgePort(ctx, &pb.CreateBridgePortRequest{ - BridgePortId: name, - BridgePort: &pb.BridgePort{ - Spec: &pb.BridgePortSpec{ - MacAddress: []byte(mac), - Ptype: typeOfPort, - LogicalBridges: logicalBridges, - }, - }, - }) - if err != nil { - log.Printf("error creating Bridge Port: %s\n", err) - return nil, err - } - - return data, nil -} - -// DeleteBridgePort delete an Bridge Port an OPI server -func (c evpnClientImpl) DeleteBridgePort(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnBridgePortClient(conn) - data, err := client.DeleteBridgePort(ctx, &pb.DeleteBridgePortRequest{ - Name: resourceIDToFullName("ports", name), - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error deleting Bridge Port: %s\n", err) - return nil, err - } - - return data, nil -} - -// GetBridgePort Get Bridge Port details -func (c evpnClientImpl) GetBridgePort(ctx context.Context, name string) (*pb.BridgePort, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnBridgePortClient(conn) - data, err := client.GetBridgePort(ctx, &pb.GetBridgePortRequest{ - Name: resourceIDToFullName("ports", name), - }) - if err != nil { - log.Printf("error getting Bridge Port: %s\n", err) - return nil, err - } - - return data, nil -} - -// ListBridgePorts list all the Bridge Port an OPI server -func (c evpnClientImpl) ListBridgePorts(ctx context.Context, pageSize int32, pageToken string) (*pb.ListBridgePortsResponse, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnBridgePortClient(conn) - data, err := client.ListBridgePorts(ctx, &pb.ListBridgePortsRequest{ - PageSize: pageSize, - PageToken: pageToken, - }) - if err != nil { - log.Printf("error list Bridge Port: %s\n", err) - return nil, err - } - - return data, nil -} - -// UpdateBridgePort update the Bridge Port on OPI server -func (c evpnClientImpl) UpdateBridgePort(ctx context.Context, name string, updateMask []string, allowMissing bool) (*pb.BridgePort, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnBridgePortClient(conn) - Port := &pb.BridgePort{ - Name: resourceIDToFullName("ports", name), - } - data, err := client.UpdateBridgePort(ctx, &pb.UpdateBridgePortRequest{ - BridgePort: Port, - UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error updating Bridge Port: %s\n", err) - return nil, err - } - - return data, nil -} - -// CreateVrf Create vrf on OPI Server -func (c evpnClientImpl) CreateVrf(ctx context.Context, name string, vni uint32, loopback string, vtep string) (*pb.Vrf, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnVRFClient(conn) - ipLoopback, err := parseIPAndPrefix(loopback) - if err != nil { - log.Printf("parseIPAndPrefix: error creating vrf: %s\n", err) - return nil, err - } - ipVtep, err := parseIPAndPrefix(vtep) - if err != nil { - log.Printf("parseIPAndPrefix: error creating vrf: %s\n", err) - return nil, err - } - data, err := client.CreateVrf(ctx, &pb.CreateVrfRequest{ - VrfId: name, - Vrf: &pb.Vrf{ - Spec: &pb.VrfSpec{ - Vni: vni, - LoopbackIpPrefix: ipLoopback, - VtepIpPrefix: ipVtep, - }, - }, - }) - if err != nil { - log.Printf("error creating vrf: %s\n", err) - return nil, err - } - - return data, nil -} - -// DeleteVrf update the vrf on OPI server -func (c evpnClientImpl) DeleteVrf(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnVRFClient(conn) - data, err := client.DeleteVrf(ctx, &pb.DeleteVrfRequest{ - Name: resourceIDToFullName("vrfs", name), - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error deleting vrf: %s\n", err) - return nil, err - } - - return data, nil -} - -// GetVrf get vrf details from OPI server -func (c evpnClientImpl) GetVrf(ctx context.Context, name string) (*pb.Vrf, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnVRFClient(conn) - data, err := client.GetVrf(ctx, &pb.GetVrfRequest{ - Name: resourceIDToFullName("vrfs", name), - }) - if err != nil { - log.Printf("error getting vrf: %s\n", err) - return nil, err - } - - return data, nil -} - -// ListVrfs list all vrf's with details from OPI server -func (c evpnClientImpl) ListVrfs(ctx context.Context, pageSize int32, pageToken string) (*pb.ListVrfsResponse, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnVRFClient(conn) - data, err := client.ListVrfs(ctx, &pb.ListVrfsRequest{ - PageSize: pageSize, - PageToken: pageToken, - }) - if err != nil { - log.Printf("error list Vrf: %s\n", err) - return nil, err - } - - return data, nil -} - -// UpdateVrf update the vrf on OPI server -func (c evpnClientImpl) UpdateVrf(ctx context.Context, name string, updateMask []string, allowMissing bool) (*pb.Vrf, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnVRFClient(conn) - vrf, err := client.GetVrf(ctx, &pb.GetVrfRequest{ - Name: resourceIDToFullName("vrfs", name), - }) - if err != nil { - log.Printf("error updating vrf: %s\n", err) - return nil, err - } - data, err := client.UpdateVrf(ctx, &pb.UpdateVrfRequest{ - Vrf: vrf, - UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error creating evpn: %s\n", err) - return nil, err - } - - return data, nil -} - -// CreateSvi create svi on OPI server -func (c evpnClientImpl) CreateSvi(ctx context.Context, name string, vrf string, logicalBridge string, mac string, gwIPs []string, ebgp bool, remoteAS uint32) (*pb.Svi, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - - client := c.getEvpnSVIClient(conn) - - gwPrefixes, err := parseIPPrefixes(gwIPs) - if err != nil { - log.Printf("error parsing GwIPs: %s\n", err) - return nil, err - } - data, err := client.CreateSvi(ctx, &pb.CreateSviRequest{ - SviId: name, - Svi: &pb.Svi{ - Spec: &pb.SviSpec{ - Vrf: vrf, - LogicalBridge: logicalBridge, - MacAddress: []byte(mac), - GwIpPrefix: gwPrefixes, - EnableBgp: ebgp, - RemoteAs: remoteAS, - }, - }, - }) - if err != nil { - log.Printf("error creating svi: %s\n", err) - return nil, err - } - - return data, nil -} - -// DeleteSvi delete the svi on OPI server -func (c evpnClientImpl) DeleteSvi(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnSVIClient(conn) - data, err := client.DeleteSvi(ctx, &pb.DeleteSviRequest{ - Name: resourceIDToFullName("svis", name), - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error deleting svi: %s\n", err) - return nil, err - } - - return data, nil -} - -// GetSvi get svi details from OPI server -func (c evpnClientImpl) GetSvi(ctx context.Context, name string) (*pb.Svi, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnSVIClient(conn) - data, err := client.GetSvi(ctx, &pb.GetSviRequest{ - Name: resourceIDToFullName("svis", name), - }) - if err != nil { - log.Printf("error getting svi: %s\n", err) - return nil, err - } - - return data, nil -} - -// ListSvis get all the svi's from OPI server -func (c evpnClientImpl) ListSvis(ctx context.Context, pageSize int32, pageToken string) (*pb.ListSvisResponse, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnSVIClient(conn) - data, err := client.ListSvis(ctx, &pb.ListSvisRequest{ - PageSize: pageSize, - PageToken: pageToken, - }) - if err != nil { - log.Printf("error list svis: %s\n", err) - return nil, err - } - - return data, nil -} - -// UpdateSvi update the svi on OPI server -func (c evpnClientImpl) UpdateSvi(ctx context.Context, name string, updateMask []string, allowMissing bool) (*pb.Svi, error) { - conn, closer, err := c.NewConn() - if err != nil { - log.Printf("error creating connection: %s\n", err) - return nil, err - } - defer closer() - client := c.getEvpnSVIClient(conn) - svi, err := client.GetSvi(ctx, &pb.GetSviRequest{ - Name: resourceIDToFullName("svis", name), - }) - if err != nil { - log.Printf("error getting svi: %s\n", err) - return nil, err - } - data, err := client.UpdateSvi(ctx, &pb.UpdateSviRequest{ - Svi: svi, - UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, - AllowMissing: allowMissing, - }) - if err != nil { - log.Printf("error updating svi: %s\n", err) - return nil, err - } - - return data, nil -} diff --git a/network/evpn_test.go b/network/evpn_test.go index df80d78..eaee0dd 100644 --- a/network/evpn_test.go +++ b/network/evpn_test.go @@ -1,4 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. // Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. // Package network implements the go library for OPI to be used to establish networking diff --git a/network/logical_bridge.go b/network/logical_bridge.go new file mode 100644 index 0000000..6d8f919 --- /dev/null +++ b/network/logical_bridge.go @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network + +import ( + "context" + "log" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" + "google.golang.org/protobuf/types/known/emptypb" + "google.golang.org/protobuf/types/known/fieldmaskpb" +) + +// CreateLogicalBridge creates an Logical Bridge an OPI server +func (c evpnClientImpl) CreateLogicalBridge(ctx context.Context, name string, vlanID uint32, vni uint32) (*pb.LogicalBridge, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnLogicalBridgeClient(conn) + + data, err := client.CreateLogicalBridge(ctx, &pb.CreateLogicalBridgeRequest{ + LogicalBridgeId: name, + LogicalBridge: &pb.LogicalBridge{ + Spec: &pb.LogicalBridgeSpec{ + VlanId: vlanID, + Vni: vni, + }, + }, + }) + if err != nil { + log.Printf("error creating logical bridge: %s\n", err) + return nil, err + } + + return data, nil +} + +// DeleteLogicalBridge deletes an Logical Bridge an OPI server +func (c evpnClientImpl) DeleteLogicalBridge(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnLogicalBridgeClient(conn) + + data, err := client.DeleteLogicalBridge(ctx, &pb.DeleteLogicalBridgeRequest{ + Name: resourceIDToFullName("bridges", name), + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error deleting logical bridge: %s\n", err) + return nil, err + } + + return data, nil +} + +// GetLogicalBridge get Logical Bridge details from OPI server +func (c evpnClientImpl) GetLogicalBridge(ctx context.Context, name string) (*pb.LogicalBridge, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnLogicalBridgeClient(conn) + + data, err := client.GetLogicalBridge(ctx, &pb.GetLogicalBridgeRequest{ + Name: resourceIDToFullName("bridges", name), + }) + if err != nil { + log.Printf("error getting logical bridge: %s\n", err) + return nil, err + } + + return data, nil +} + +// ListLogicalBridges list all Logical Bridge details from OPI server +func (c evpnClientImpl) ListLogicalBridges(ctx context.Context, pageSize int32, pageToken string) (*pb.ListLogicalBridgesResponse, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnLogicalBridgeClient(conn) + + data, err := client.ListLogicalBridges(ctx, &pb.ListLogicalBridgesRequest{ + PageSize: pageSize, + PageToken: pageToken, + }) + if err != nil { + log.Printf("error List logical bridge: %s\n", err) + return nil, err + } + + return data, nil +} + +// UpdateLogicalBridge update Logical Bridge on OPI server +func (c evpnClientImpl) UpdateLogicalBridge(ctx context.Context, name string, updateMask []string) (*pb.LogicalBridge, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnLogicalBridgeClient(conn) + Bridge := &pb.LogicalBridge{ + Name: resourceIDToFullName("bridges", name), + } + data, err := client.UpdateLogicalBridge(ctx, &pb.UpdateLogicalBridgeRequest{ + LogicalBridge: Bridge, + UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, + }) + if err != nil { + log.Printf("error Update logical bridge: %s\n", err) + return nil, err + } + + return data, nil +} diff --git a/network/logical_bridge_test.go b/network/logical_bridge_test.go new file mode 100644 index 0000000..eaee0dd --- /dev/null +++ b/network/logical_bridge_test.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network diff --git a/network/svi.go b/network/svi.go new file mode 100644 index 0000000..c3b3e11 --- /dev/null +++ b/network/svi.go @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network + +import ( + "context" + "log" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" + "google.golang.org/protobuf/types/known/emptypb" + "google.golang.org/protobuf/types/known/fieldmaskpb" +) + +// CreateSvi create svi on OPI server +func (c evpnClientImpl) CreateSvi(ctx context.Context, name string, vrf string, logicalBridge string, mac string, gwIPs []string, ebgp bool, remoteAS uint32) (*pb.Svi, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnSVIClient(conn) + + gwPrefixes, err := parseIPPrefixes(gwIPs) + if err != nil { + log.Printf("error parsing GwIPs: %s\n", err) + return nil, err + } + data, err := client.CreateSvi(ctx, &pb.CreateSviRequest{ + SviId: name, + Svi: &pb.Svi{ + Spec: &pb.SviSpec{ + Vrf: vrf, + LogicalBridge: logicalBridge, + MacAddress: []byte(mac), + GwIpPrefix: gwPrefixes, + EnableBgp: ebgp, + RemoteAs: remoteAS, + }, + }, + }) + if err != nil { + log.Printf("error creating svi: %s\n", err) + return nil, err + } + + return data, nil +} + +// DeleteSvi delete the svi on OPI server +func (c evpnClientImpl) DeleteSvi(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnSVIClient(conn) + data, err := client.DeleteSvi(ctx, &pb.DeleteSviRequest{ + Name: resourceIDToFullName("svis", name), + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error deleting svi: %s\n", err) + return nil, err + } + + return data, nil +} + +// GetSvi get svi details from OPI server +func (c evpnClientImpl) GetSvi(ctx context.Context, name string) (*pb.Svi, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnSVIClient(conn) + data, err := client.GetSvi(ctx, &pb.GetSviRequest{ + Name: resourceIDToFullName("svis", name), + }) + if err != nil { + log.Printf("error getting svi: %s\n", err) + return nil, err + } + + return data, nil +} + +// ListSvis get all the svi's from OPI server +func (c evpnClientImpl) ListSvis(ctx context.Context, pageSize int32, pageToken string) (*pb.ListSvisResponse, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnSVIClient(conn) + data, err := client.ListSvis(ctx, &pb.ListSvisRequest{ + PageSize: pageSize, + PageToken: pageToken, + }) + if err != nil { + log.Printf("error list svis: %s\n", err) + return nil, err + } + + return data, nil +} + +// UpdateSvi update the svi on OPI server +func (c evpnClientImpl) UpdateSvi(ctx context.Context, name string, updateMask []string, allowMissing bool) (*pb.Svi, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnSVIClient(conn) + svi, err := client.GetSvi(ctx, &pb.GetSviRequest{ + Name: resourceIDToFullName("svis", name), + }) + if err != nil { + log.Printf("error getting svi: %s\n", err) + return nil, err + } + data, err := client.UpdateSvi(ctx, &pb.UpdateSviRequest{ + Svi: svi, + UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error updating svi: %s\n", err) + return nil, err + } + + return data, nil +} diff --git a/network/svi_test.go b/network/svi_test.go new file mode 100644 index 0000000..eaee0dd --- /dev/null +++ b/network/svi_test.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network diff --git a/network/utils.go b/network/utils.go new file mode 100644 index 0000000..0f73bc9 --- /dev/null +++ b/network/utils.go @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network + +import ( + "fmt" + "net" + "strconv" + "strings" + + pc "github.com/opiproject/opi-api/network/opinetcommon/v1alpha1/gen/go" +) + +// Function to convert IPv4 address from net.IP to uint32 +func ip4ToInt(ip net.IP) uint32 { + return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3]) +} + +// Function to parse IP address and prefix from a string of the form "IP/PREFIX" +func parseIPAndPrefix(ipPrefixStr string) (*pc.IPPrefix, error) { + parts := strings.Split(ipPrefixStr, "/") + if len(parts) != 2 { + return nil, fmt.Errorf("invalid IP address with prefix: %s", ipPrefixStr) + } + + ipAddress := parts[0] + prefixLength64, err := strconv.ParseInt(parts[1], 10, 32) + + if err != nil { + return nil, fmt.Errorf("failed to parse prefix length: %s", err) + } + + prefixLength := int32(prefixLength64) + + ip := net.ParseIP(ipAddress) + if ip == nil { + return nil, fmt.Errorf("invalid IP address: %s", ipAddress) + } + + addressFamily := int32(0) + var ipv4Addr uint32 + var ipv6Addr []byte + var addr *pc.IPAddress + if ip.To4() != nil { + addressFamily = 1 // IPv4 + ipv4Addr = ip4ToInt(ip.To4()) + addr = &pc.IPAddress{ + Af: pc.IpAf(addressFamily), + V4OrV6: &pc.IPAddress_V4Addr{ + V4Addr: ipv4Addr, + }, + } + } else { + addressFamily = 2 // IPv6 + ipv6Addr = ip.To16() + addr = &pc.IPAddress{ + Af: pc.IpAf(addressFamily), + V4OrV6: &pc.IPAddress_V6Addr{ + V6Addr: ipv6Addr, + }, + } + } + return &pc.IPPrefix{ + Addr: addr, + Len: prefixLength, + }, nil +} + +// Function to parse an array of IP prefixes from strings to pb.IPPrefix messages +func parseIPPrefixes(ipPrefixesStr []string) ([]*pc.IPPrefix, error) { + const maxPrefixes = 10 // Update this to your expected maximum number of prefixes + var ipPrefixes = make([]*pc.IPPrefix, 0, maxPrefixes) + + for _, ipPrefixStr := range ipPrefixesStr { + ipPrefix, err := parseIPAndPrefix(ipPrefixStr) + if err != nil { + return nil, fmt.Errorf("failed to parse IP prefix: %v", err) + } + ipPrefixes = append(ipPrefixes, ipPrefix) + } + return ipPrefixes, nil +} diff --git a/network/vrf.go b/network/vrf.go new file mode 100644 index 0000000..6fda974 --- /dev/null +++ b/network/vrf.go @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network + +import ( + "context" + "log" + + pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go" + "google.golang.org/protobuf/types/known/emptypb" + "google.golang.org/protobuf/types/known/fieldmaskpb" +) + +// CreateVrf Create vrf on OPI Server +func (c evpnClientImpl) CreateVrf(ctx context.Context, name string, vni uint32, loopback string, vtep string) (*pb.Vrf, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + + client := c.getEvpnVRFClient(conn) + ipLoopback, err := parseIPAndPrefix(loopback) + if err != nil { + log.Printf("parseIPAndPrefix: error creating vrf: %s\n", err) + return nil, err + } + ipVtep, err := parseIPAndPrefix(vtep) + if err != nil { + log.Printf("parseIPAndPrefix: error creating vrf: %s\n", err) + return nil, err + } + data, err := client.CreateVrf(ctx, &pb.CreateVrfRequest{ + VrfId: name, + Vrf: &pb.Vrf{ + Spec: &pb.VrfSpec{ + Vni: vni, + LoopbackIpPrefix: ipLoopback, + VtepIpPrefix: ipVtep, + }, + }, + }) + if err != nil { + log.Printf("error creating vrf: %s\n", err) + return nil, err + } + + return data, nil +} + +// DeleteVrf update the vrf on OPI server +func (c evpnClientImpl) DeleteVrf(ctx context.Context, name string, allowMissing bool) (*emptypb.Empty, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnVRFClient(conn) + data, err := client.DeleteVrf(ctx, &pb.DeleteVrfRequest{ + Name: resourceIDToFullName("vrfs", name), + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error deleting vrf: %s\n", err) + return nil, err + } + + return data, nil +} + +// GetVrf get vrf details from OPI server +func (c evpnClientImpl) GetVrf(ctx context.Context, name string) (*pb.Vrf, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnVRFClient(conn) + data, err := client.GetVrf(ctx, &pb.GetVrfRequest{ + Name: resourceIDToFullName("vrfs", name), + }) + if err != nil { + log.Printf("error getting vrf: %s\n", err) + return nil, err + } + + return data, nil +} + +// ListVrfs list all vrf's with details from OPI server +func (c evpnClientImpl) ListVrfs(ctx context.Context, pageSize int32, pageToken string) (*pb.ListVrfsResponse, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnVRFClient(conn) + data, err := client.ListVrfs(ctx, &pb.ListVrfsRequest{ + PageSize: pageSize, + PageToken: pageToken, + }) + if err != nil { + log.Printf("error list Vrf: %s\n", err) + return nil, err + } + + return data, nil +} + +// UpdateVrf update the vrf on OPI server +func (c evpnClientImpl) UpdateVrf(ctx context.Context, name string, updateMask []string, allowMissing bool) (*pb.Vrf, error) { + conn, closer, err := c.NewConn() + if err != nil { + log.Printf("error creating connection: %s\n", err) + return nil, err + } + defer closer() + client := c.getEvpnVRFClient(conn) + vrf, err := client.GetVrf(ctx, &pb.GetVrfRequest{ + Name: resourceIDToFullName("vrfs", name), + }) + if err != nil { + log.Printf("error updating vrf: %s\n", err) + return nil, err + } + data, err := client.UpdateVrf(ctx, &pb.UpdateVrfRequest{ + Vrf: vrf, + UpdateMask: &fieldmaskpb.FieldMask{Paths: updateMask}, + AllowMissing: allowMissing, + }) + if err != nil { + log.Printf("error creating evpn: %s\n", err) + return nil, err + } + + return data, nil +} diff --git a/network/vrf_test.go b/network/vrf_test.go new file mode 100644 index 0000000..eaee0dd --- /dev/null +++ b/network/vrf_test.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package network implements the go library for OPI to be used to establish networking +package network