Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding evpn use case files to opi-intel-bridge #491

Merged
merged 4 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ ENV CGO_ENABLED=0
# build an app
COPY cmd/ cmd/
COPY pkg/ pkg/
RUN go build -v -o /opi-intel-bridge ./cmd/...

RUN go build -v -o /opi-intel-bridge-storage ./cmd/storage && \
go build -v -o /opi-intel-bridge-evpn ./cmd/evpn
# second stage to reduce image size
FROM alpine:3.19@sha256:51b67269f354137895d43f3b3d810bfacd3945438e94dc5ac55fdac340352f48
RUN apk add --no-cache --no-check-certificate hwdata && rm -rf /var/cache/apk/*
COPY --from=builder /opi-intel-bridge /
COPY --from=builder /opi-intel-bridge-storage /
COPY --from=builder /opi-intel-bridge-evpn /
COPY --from=docker.io/fullstorydev/grpcurl:v1.8.9-alpine /bin/grpcurl /usr/local/bin/
EXPOSE 50051
CMD [ "/opi-intel-bridge", "-grpc_port=50051", "-http_port=8082" ]
CMD [ "/opi-intel-bridge-storage", "-grpc_port=50051", "-http_port=8082" ]
HEALTHCHECK CMD grpcurl -plaintext localhost:50051 list || exit 1
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ MAKEFLAGS += --silent

compile: get build

build:
build: build-evpn build-storage
build-evpn:
@echo " > Building binaries..."
@CGO_ENABLED=0 go build -o ${PROJECTNAME} ./cmd/...
@CGO_ENABLED=0 go build -o ${PROJECTNAME}-evpn ./cmd/evpn

build-storage:
@echo " > Building binaries..."
@CGO_ENABLED=0 go build -o ${PROJECTNAME}-storage ./cmd/storage

get:
@echo " > Checking if there are any missing dependencies..."
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ The following variables are used throughout this document:
To build the solution execute

```bash
go build -v -o /opi-intel-bridge ./cmd/...
go build -v -o /opi-intel-bridge-storage ./cmd/storage
```

To import the bridge within another go package or module use

```go
import "github.com/opiproject/opi-intel-bridge/pkg/frontend"
import "github.com/opiproject/opi-intel-bridge-storage/pkg/frontend"
```

### Usage
Expand All @@ -86,7 +86,7 @@ Make sure `/var/tmp/spdk.sock` is created.
On xPU run

```bash
$ docker run --rm -it -v /var/tmp/:/var/tmp/ -p $BRIDGE_PORT:$BRIDGE_PORT -p $BRIDGE_HTTP_PORT:$BRIDGE_HTTP_PORT ghcr.io/opiproject/opi-intel-bridge:main /opi-intel-bridge -grpc_port=$BRIDGE_PORT -http_port=$BRIDGE_HTTP_PORT
$ docker run --rm -it -v /var/tmp/:/var/tmp/ -p $BRIDGE_PORT:$BRIDGE_PORT -p $BRIDGE_HTTP_PORT:$BRIDGE_HTTP_PORT ghcr.io/opiproject/opi-intel-bridge:main /opi-intel-bridge-storage -grpc_port=$BRIDGE_PORT -http_port=$BRIDGE_HTTP_PORT

2023/09/12 20:29:05 TLS files are not specified. Use insecure connection.
2023/09/12 20:29:05 Connection to SPDK will be via: unix detected from /var/tmp/spdk.sock
Expand Down Expand Up @@ -345,7 +345,7 @@ make sure to follow the principle of least privilege for access permissions and
Run bridge binary specifying TLS-related server key/certificate and CA cert

```bash
./opi-intel-bridge -grpc_port=$BRIDGE_PORT -http_port=$BRIDGE_HTTP_PORT -tls $SERVER_CERT:$SERVER_KEY:$CA_CERT
./opi-intel-bridge-storage -grpc_port=$BRIDGE_PORT -http_port=$BRIDGE_HTTP_PORT -tls $SERVER_CERT:$SERVER_KEY:$CA_CERT
```

for container
Expand Down
305 changes: 305 additions & 0 deletions cmd/evpn/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries.
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.
// Copyright (C) 2023 Nordix Foundation.

// Package main is the main package of the application
//
//nolint:all
package main

import (
"context"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"

pc "github.com/opiproject/opi-api/inventory/v1/gen/go"
pe "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"
"github.com/opiproject/opi-evpn-bridge/pkg/bridge"
"github.com/opiproject/opi-evpn-bridge/pkg/config"
"github.com/opiproject/opi-evpn-bridge/pkg/infradb"
"github.com/opiproject/opi-evpn-bridge/pkg/infradb/taskmanager"
"github.com/opiproject/opi-evpn-bridge/pkg/port"
"github.com/opiproject/opi-evpn-bridge/pkg/svi"
"github.com/opiproject/opi-evpn-bridge/pkg/utils"
"github.com/opiproject/opi-evpn-bridge/pkg/vrf"
"github.com/opiproject/opi-smbios-bridge/pkg/inventory"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/reflection"

"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
gen_linux "github.com/opiproject/opi-evpn-bridge/pkg/LinuxGeneralModule"
frr "github.com/opiproject/opi-evpn-bridge/pkg/frr"
netlink "github.com/opiproject/opi-evpn-bridge/pkg/netlink"
intel_e2000_linux "github.com/opiproject/opi-intel-bridge/pkg/evpn/LinuxVendorModule/intele2000"
"github.com/opiproject/opi-intel-bridge/pkg/evpn/vendor_plugins/intel-e2000/p4runtime/p4driverapi"
ipu_vendor "github.com/opiproject/opi-intel-bridge/pkg/evpn/vendor_plugins/intel-e2000/p4runtime/p4translation"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
)

const (
intelStr = "intel_e2000"
)

var rootCmd = &cobra.Command{
Use: "opi-evpn-bridge",
Short: "evpn bridge",
Long: "evpn bridge application",

Run: func(_ *cobra.Command, _ []string) {

taskmanager.TaskMan.StartTaskManager()

err := infradb.NewInfraDB(config.GlobalConfig.DBAddress, config.GlobalConfig.Database)
if err != nil {
log.Panicf("Error: %v", err)
}
go runGatewayServer(config.GlobalConfig.GRPCPort, config.GlobalConfig.HTTPPort)

switch config.GlobalConfig.Buildenv {
case intelStr:
gen_linux.Initialize()
intel_e2000_linux.Initialize()
frr.Initialize()
ipu_vendor.Initialize()
default:
log.Panic(" ERROR: Could not find Build env ")
}

// Create GRD VRF configuration during startup
if err := createGrdVrf(); err != nil {
log.Panicf("Error: %v", err)
}
switch config.GlobalConfig.Buildenv {
case intelStr:
netlink.Initialize()
default:
}
runGrpcServer(config.GlobalConfig.GRPCPort, config.GlobalConfig.TLSFiles)

},
}

// initialize the cobra configuration and bind the flags
func initialize() error {
cobra.OnInitialize(config.Initcfg)

rootCmd.PersistentFlags().StringVarP(&config.GlobalConfig.CfgFile, "config", "c", "config.yaml", "config file path")
rootCmd.PersistentFlags().Uint16Var(&config.GlobalConfig.GRPCPort, "grpcport", 50151, "The gRPC server port")
rootCmd.PersistentFlags().Uint16Var(&config.GlobalConfig.HTTPPort, "httpport", 8082, "The HTTP server port")
rootCmd.PersistentFlags().StringVar(&config.GlobalConfig.TLSFiles, "tlsfiles", "", "TLS files in server_cert:server_key:ca_cert format.")
rootCmd.PersistentFlags().StringVar(&config.GlobalConfig.DBAddress, "dbaddress", "127.0.0.1:6379", "db address in ip_address:port format")
rootCmd.PersistentFlags().StringVar(&config.GlobalConfig.Database, "database", "redis", "Database connection string")

// Bind command-line flags to config fields
if err := viper.GetViper().BindPFlags(rootCmd.PersistentFlags()); err != nil {
log.Printf("Error binding flags to Viper: %v\n", err)
return err
}

return nil
}

const logfile string = "opi-evpn-bridge.log"

var logger *log.Logger

// setupLogger sets the config for logger
func setupLogger(filename string) {
var err error
filename = filepath.Clean(filename)
out, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Panic(err)
}
logger = log.New(io.MultiWriter(out), "", log.Lshortfile|log.LstdFlags)
log.SetOutput(logger.Writer())
}

func cleanUp() {
log.Println("Defer function called")
if err := infradb.DeleteAllResources(); err != nil {
log.Println("Failed to delete all the resources: ", err)
}
switch config.GlobalConfig.Buildenv {
case intelStr:
gen_linux.DeInitialize()
intel_e2000_linux.DeInitialize()
frr.DeInitialize()
netlink.DeInitialize()
ipu_vendor.DeInitialize()
close(p4driverapi.StopCh)

default:
log.Panic(" ERROR: Could not find Build env ")
}

if err := infradb.Close(); err != nil {
log.Println("Failed to close infradb")
}
}

// main function
func main() {
// setup file and console logger
setupLogger(logfile)

// initialize cobra config
if err := initialize(); err != nil {
log.Panicf("Error in initialize(): %v", err)
}

sigChan := make(chan os.Signal, 1)
// Notify sigChan on SIGINT or SIGTERM.
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

// This goroutine executes a blocking receive for signals.
// When it gets one it will then exit the program.
go func() {
sig := <-sigChan
switch sig {
case syscall.SIGINT:
cleanUp()
fmt.Println("Received SIGINT, shutting down.")
case syscall.SIGTERM:
cleanUp()
fmt.Println("Received SIGTERM, shutting down.")
default:
fmt.Println("Received unknown signal.")
}
// Exit the program.
os.Exit(0)
}()

// start the main cmd
if err := rootCmd.Execute(); err != nil {
log.Panicf("Error in Execute(): %v", err)
}
defer cleanUp()
}

// runGrpcServer start the grpc server for all the components
func runGrpcServer(grpcPort uint16, tlsFiles string) {
if config.GlobalConfig.Tracer {
tp := utils.InitTracerProvider("opi-evpn-bridge")
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Panicf("Tracer Provider Shutdown: %v", err)
}
}()
}

lis, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort))
if err != nil {
log.Panicf("failed to listen: %v", err)
}

var serverOptions []grpc.ServerOption
if tlsFiles == "" {
log.Println("TLS files are not specified. Use insecure connection.")
} else {
log.Println("Use TLS certificate files:", tlsFiles)
config, err := utils.ParseTLSFiles(tlsFiles)
if err != nil {
log.Panic("Failed to parse string with tls paths:", err)
}
log.Println("TLS config:", config)
var option grpc.ServerOption
if option, err = utils.SetupTLSCredentials(config); err != nil {
log.Panic("Failed to setup TLS:", err)
}
serverOptions = append(serverOptions, option)
}

serverOptions = append(serverOptions,
grpc.StatsHandler(otelgrpc.NewServerHandler()),
grpc.UnaryInterceptor(
logging.UnaryServerInterceptor(utils.InterceptorLogger(log.Default()),
logging.WithLogOnEvents(
logging.StartCall,
logging.FinishCall,
logging.PayloadReceived,
logging.PayloadSent,
),
)),
)
s := grpc.NewServer(serverOptions...)

bridgeServer := bridge.NewServer()
portServer := port.NewServer()
vrfServer := vrf.NewServer()
sviServer := svi.NewServer()
pe.RegisterLogicalBridgeServiceServer(s, bridgeServer)
pe.RegisterBridgePortServiceServer(s, portServer)
pe.RegisterVrfServiceServer(s, vrfServer)
pe.RegisterSviServiceServer(s, sviServer)
pc.RegisterInventoryServiceServer(s, &inventory.Server{})

reflection.Register(s)

log.Printf("gRPC server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Panicf("failed to serve: %v", err)
}
}

// runGatewayServer
func runGatewayServer(grpcPort uint16, httpPort uint16) {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()

// Register gRPC server endpoint
// Note: Make sure the gRPC server is running properly and accessible
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}

// TODO: add/replace with more/less registrations, once opi-api compiler fixed
err := pc.RegisterInventoryServiceHandlerFromEndpoint(ctx, mux, fmt.Sprintf(":%d", grpcPort), opts)
if err != nil {
log.Panic("cannot register handler server")
}

// Start HTTP server (and proxy calls to gRPC server endpoint)
log.Printf("HTTP Server listening at %v", httpPort)
server := &http.Server{
Addr: fmt.Sprintf(":%d", httpPort),
Handler: mux,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
err = server.ListenAndServe()
if err != nil {
log.Panic("cannot start HTTP gateway server")
}
}

// createGrdVrf creates the grd vrf with vni 0
func createGrdVrf() error {
grdVrf, err := infradb.NewVrfWithArgs("//network.opiproject.org/vrfs/GRD", nil, nil, nil)
if err != nil {
log.Printf("CreateGrdVrf(): Error in initializing GRD VRF object %+v\n", err)
return err
}

err = infradb.CreateVrf(grdVrf)
if err != nil {
log.Printf("CreateGrdVrf(): Error in creating GRD VRF object %+v\n", err)
return err
}

return nil
}
2 changes: 1 addition & 1 deletion cmd/main.go → cmd/storage/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"time"

"github.com/opiproject/gospdk/spdk"
fe "github.com/opiproject/opi-intel-bridge/pkg/frontend"
fe "github.com/opiproject/opi-intel-bridge/pkg/storage/frontend"
"github.com/opiproject/opi-smbios-bridge/pkg/inventory"
"github.com/opiproject/opi-spdk-bridge/pkg/backend"
"github.com/opiproject/opi-spdk-bridge/pkg/frontend"
Expand Down
Loading
Loading