Skip to content
Closed
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
1 change: 0 additions & 1 deletion BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
# gazelle:prefix github.com/openconfig/lemming
# gazelle:resolve proto go google/rpc/status.proto @org_golang_google_genproto_googleapis_rpc//status
# gazelle:resolve proto google/rpc/status.proto @googleapis//google/rpc:status_proto
# gazelle:resolve go github.com/openconfig/lemming/dataplane/proto/sai //dataplane/proto/sai:sai
# gazelle:build_file_name BUILD
# gazelle:exclude github.com/p4lang/p4runtime
gazelle(
Expand Down
41 changes: 17 additions & 24 deletions Dockerfile.saibuilder
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
FROM debian:bookworm

# Install required build packages and development libraries
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
clang \
git \
wget \
unzip \
ca-certificates \
libnl-genl-3-dev \
libnl-3-dev \
libpcap-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Install Bazelisk
RUN wget -q -O /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-amd64 && \
chmod +x /usr/local/bin/bazel

FROM us-west1-docker.pkg.dev/openconfig-lemming/internal/builder@sha256:6a960d06bfd63c9cd8cff1f2ab3b3cc21e578b570979b5574d232be644dd0bf9
WORKDIR /build
COPY . .

RUN bazel build --lockfile_mode=off --dynamic_mode=off //dataplane/standalone:sai && \
cp bazel-bin/dataplane/standalone/libsai.so /build/libsai.so
COPY patches/sai.patch sai.patch
RUN wget -q https://github.com/opencomputeproject/SAI/archive/refs/tags/v1.14.0.tar.gz && tar xf v1.14.0.tar.gz && rm v1.14.0.tar.gz
RUN mkdir external && mv SAI-1.14.0 external/com_github_opencomputeproject_sai && patch -p1 -d external/com_github_opencomputeproject_sai < sai.patch
COPY go.* .
COPY dataplane/proto/sai/*.proto dataplane/proto/sai/
COPY dataplane/cpusink/*.go dataplane/cpusink/
COPY dataplane/standalone/packetio/*.go dataplane/standalone/packetio/
COPY dataplane/dplaneopts/*.go dataplane/dplaneopts/
COPY dataplane/forwarding/ dataplane/forwarding/
COPY dataplane/internal/kernel/*.go dataplane/internal/kernel/
COPY proto/forwarding/*.go proto/forwarding/
COPY dataplane/standalone/sai/*.cc dataplane/standalone/sai/
COPY dataplane/standalone/sai/*.h dataplane/standalone/sai/
COPY dataplane/standalone/entrypoint.cc dataplane/standalone/entrypoint.cc
COPY Makefile .
RUN make lucius-libsai -j 48
23 changes: 3 additions & 20 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ bazel_dep(name = "protobuf", version = "29.3", repo_name = "com_google_protobuf"
bazel_dep(name = "re2", version = "2024-07-02.bcr.1")
bazel_dep(name = "rules_go", version = "0.57.0", repo_name = "io_bazel_rules_go")
bazel_dep(name = "rules_pkg", version = "1.1.0")
bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_proto", version = "7.0.2")
bazel_dep(name = "rules_proto_grpc_go", version = "5.0.1")
bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "rules_distroless", version = "0.5.1")
Expand All @@ -31,30 +31,13 @@ archive_override(

http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "doxygen_release",
build_file_content = 'exports_files(["bin/doxygen"], ["//visibility:public"])',
sha256 = "610697eba6104110389d371e6908ed35b4b00f9e650c969a213dc0020b067a55",
strip_prefix = "doxygen-1.8.16",
type = "tar.gz",
urls = ["https://sourceforge.net/projects/doxygen/files/rel-1.8.16/doxygen-1.8.16.linux.bin.tar.gz/download"],
)

http_archive(
name = "com_github_opencomputeproject_sai",
build_file_content = """
exports_files(["meta/Doxyfile"])

filegroup(
name = "headers",
srcs = glob(["inc/**/*.h", "experimental/**/*.h", "meta/**/*.h"]),
visibility = ["//visibility:public"],
)

cc_library(
name = "sai",
hdrs = [":headers"],
includes = ["inc", "experimental", "meta"],
hdrs = glob(["inc/*.h","experimental/*.h"]),
includes = ["inc", "experimental"],
visibility = ["//visibility:public"],
)
""",
Expand Down
3 changes: 1 addition & 2 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,5 @@ lucius-libsai: libsai.so
lucius-libsai-bullseye:
DOCKER_BUILDKIT=1 docker build . -f Dockerfile.saibuilder -t lemming-libsai:latest
docker create --name libsai-temp lemming-libsai:latest
docker cp libsai-temp:/build/libsai.so ./libsai.so
docker cp libsai-temp:/build/pkg/lucius-libsai.deb .
docker rm libsai-temp
78 changes: 10 additions & 68 deletions dataplane/apigen/apigen.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strings"

"github.com/openconfig/lemming/dataplane/apigen/ccgen"
"github.com/openconfig/lemming/dataplane/apigen/docparser"
Expand Down Expand Up @@ -60,43 +58,15 @@ func parse(headers []string, includePaths ...string) (*cc.AST, error) {
}

var (
saiPath = flag.String("sai_path", "bazel-lemming/external/com_github_opencomputeproject_sai", "Path to SAI repo")
clientOutDir = flag.String("client_out_dir", "dataplane/standalone/sai", "Output directory for C++ client code")
serverOutDir = flag.String("server_out_dir", "dataplane/standalone/saiserver", "Output directory for C++ server code")
protoOutDir = flag.String("proto_out_dir", "dataplane/proto/sai", "Output dirrectory for proto code")
protoImportPath = flag.String("proto_import_path", "", "Proto import path inside generated includes (falls back to -proto_out_dir if empty)")
protoPackage = flag.String("proto_package", "lemming.dataplane.sai", "Package for generated proto code")
protoGoPackage = flag.String("proto_go_package", "github.com/openconfig/lemming/dataplane/proto/sai", "Go package option in proto code")
xmlPath = flag.String("xml_path", "dataplane/apigen/xml", "Path to generate SAI doxygen XML files.")
apis = flag.String("apis", "", "Comma-separated list of APIs to generate. If empty, generate all.")
saiPath = flag.String("sai_path", "bazel-lemming/external/com_github_opencomputeproject_sai", "Path to SAI repo")
clientOutDir = flag.String("client_out_dir", "dataplane/standalone/sai", "Output directory for C++ client code")
serverOutDir = flag.String("server_out_dir", "dataplane/standalone/saiserver", "Output directory for C++ server code")
protoOutDir = flag.String("proto_out_dir", "dataplane/proto/sai", "Output dirrectory for proto code")
protoPackage = flag.String("proto_package", "lemming.dataplane.sai", "Package for generated proto code")
protoGoPackage = flag.String("proto_go_package", "github.com/openconfig/lemming/dataplane/proto/sai", "Go package option in proto code")
xmlPath = flag.String("xml_path", "dataplane/apigen/xml", "Path to generate SAI doxygen XML files.")
)

var virtualAttributes = map[string][]*docparser.AttrTypeName{
"SWITCH": {
{
EnumName: "SAI_SWITCH_ATTR_SUPPORTED_DEBUG_COUNTER_TYPE_LIST",
MemberName: "supported_debug_counter_type_list",
SaiType: "sai_s32_list_t sai_debug_counter_type_t",
Comment: "Supported debug counter types",
Value: 2112,
},
{
EnumName: "SAI_SWITCH_ATTR_SUPPORTED_INGRESS_DROP_REASON_LIST",
MemberName: "supported_ingress_drop_reason_list",
SaiType: "sai_s32_list_t sai_in_drop_reason_t",
Comment: "Supported ingress drop reasons",
Value: 2113,
},
{
EnumName: "SAI_SWITCH_ATTR_AVAILABLE_SWITCH_INGRESS_DROP_COUNTERS",
MemberName: "available_switch_ingress_drop_counters",
SaiType: "sai_uint32_t",
Comment: "Available ingress drop counters",
Value: 2118,
},
},
}

func generate() error {
saiHeaderFile, err := filepath.Abs(filepath.Join(*saiPath, "inc/sai.h"))
if err != nil {
Expand All @@ -119,48 +89,20 @@ func generate() error {
return err
}
sai := saiast.Get(ast)
var allAPIs []string
for _, iface := range sai.Ifaces {
allAPIs = append(allAPIs, strings.TrimSuffix(strings.TrimPrefix(iface.Name, "sai_"), "_api_t"))
}
slices.SortFunc(allAPIs, func(a, b string) int {
return len(b) - len(a)
})

var apiList []string
if *apis != "" {
for _, api := range strings.Split(*apis, ",") {
apiList = append(apiList, strings.TrimSpace(api))
}
sai.Filter(apiList)
}
xmlInfo, err := docparser.ParseSAIXMLDir(*xmlPath)
if err != nil {
return err
}
if *apis != "" {
xmlInfo.Filter(apiList, allAPIs)
}

for api, attrs := range virtualAttributes {
xmlInfo.Attrs[api].ReadFields = append(xmlInfo.Attrs[api].ReadFields, attrs...)
}

// Use proto_import_path to set the include path prefix for generated C++ headers.
// Fall back to proto_out_dir if not specified (e.g. for standalone builds).
importPath := *protoImportPath
if importPath == "" {
importPath = *protoOutDir
}
protos, err := protogen.Generate(xmlInfo, sai, *protoPackage, *protoGoPackage, importPath)
protos, err := protogen.Generate(xmlInfo, sai, *protoPackage, *protoGoPackage, *protoOutDir)
if err != nil {
return err
}
clientFiles, err := ccgen.GenClient(xmlInfo, sai, importPath, *clientOutDir, virtualAttributes)
clientFiles, err := ccgen.GenClient(xmlInfo, sai, *protoOutDir, *clientOutDir)
if err != nil {
return err
}
serverFiles, err := ccgen.GenServer(xmlInfo, sai, importPath, *serverOutDir)
serverFiles, err := ccgen.GenServer(xmlInfo, sai, *protoOutDir, *serverOutDir)
if err != nil {
return err
}
Expand Down
36 changes: 11 additions & 25 deletions dataplane/apigen/ccgen/ccgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package ccgen

import (
"fmt"
"slices"
"strings"
"text/template"
Expand All @@ -30,20 +29,12 @@ var unsupportedEnum = map[string]struct{}{
}

// GenClient generates the C++ code for the SAI library.
func GenClient(doc *docparser.SAIInfo, sai *saiast.SAIAPI, protoOutDir, ccOutDir string, virtualAttrs map[string][]*docparser.AttrTypeName) (map[string]string, error) {
func GenClient(doc *docparser.SAIInfo, sai *saiast.SAIAPI, protoOutDir, ccOutDir string) (map[string]string, error) {
files := make(map[string]string)
enums := enumFile{
ProtoOutDir: protoOutDir,
CCOutDir: ccOutDir,
}
for api, attrs := range virtualAttrs {
castType := fmt.Sprintf("sai_%s_attr_t", strings.ToLower(api))
for _, attr := range attrs {
enums.VirtualDefines = append(enums.VirtualDefines, fmt.Sprintf("#define %s (%s)%d", attr.EnumName, castType, attr.Value))
}
}
slices.Sort(enums.VirtualDefines)

d, err := typeinfo.Data(doc, sai, "", "", ccOutDir, protoOutDir)
if err != nil {
return nil, err
Expand Down Expand Up @@ -217,9 +208,9 @@ switch ({{ .Var }}) {
// See the License for the specific language governing permissions and
// limitations under the License.

#include "{{ .Header }}"
#include "common.h"
#include "enum.h"
#include "{{ .CCOutDir }}/{{ .Header }}"
#include "{{ .CCOutDir }}/common.h"
#include "{{ .CCOutDir }}/enum.h"
#include "{{ .ProtoOutDir }}/common.pb.h"
#include "{{ .ProtoOutDir }}/{{ .ProtoInclude }}.h"
#include <glog/logging.h>
Expand Down Expand Up @@ -486,10 +477,6 @@ extern "C" {
#include "experimental/saiextensions.h"
}

{{ range .VirtualDefines }}
{{ . }}
{{ end }}

{{ range .Enums }}
lemming::dataplane::sai::{{ .ProtoName }} convert_{{ .SAIName }}_to_proto(const sai_int32_t val);
{{ .SAIName }} convert_{{ .SAIName }}_to_sai(lemming::dataplane::sai::{{ .ProtoName }} val);
Expand All @@ -514,7 +501,7 @@ void convert_list_{{ .SAIName }}_to_sai(int32_t *list, const google::protobuf::R
// See the License for the specific language governing permissions and
// limitations under the License.

#include "enum.h"
#include "{{ .CCOutDir }}/enum.h"

{{ range .Enums }}
{{$enum := .}}
Expand All @@ -529,9 +516,9 @@ lemming::dataplane::sai::{{ .ProtoName }} convert_{{ .SAIName }}_to_proto(const
{{ .SAIName }} convert_{{ .SAIName }}_to_sai(lemming::dataplane::sai::{{ .ProtoName }} val) {
switch (val) {
{{ range .Elems }}
case lemming::dataplane::sai::{{ .ProtoName}}: return static_cast<{{ $enum.SAIName }}>({{ .SAIName}});
case lemming::dataplane::sai::{{ .ProtoName}}: return {{ .SAIName}};
{{ end }}
default: return static_cast<{{ $enum.SAIName }}>({{ $enum.DefaultReturn }});
default: return {{ $enum.DefaultReturn }};
}
}

Expand All @@ -554,11 +541,10 @@ void convert_list_{{ .SAIName }}_to_sai(int32_t *list, const google::protobuf::R
)

type enumFile struct {
ProtoIncludes []string
Enums []enum
ProtoOutDir string
CCOutDir string
VirtualDefines []string
ProtoIncludes []string
Enums []enum
ProtoOutDir string
CCOutDir string
}

type enum struct {
Expand Down
Loading