From f8d607da59bc2a759da49aa6433ae0ec0abe616f Mon Sep 17 00:00:00 2001 From: Sayan Bandyopadhyay Date: Fri, 18 Oct 2024 08:26:15 -0400 Subject: [PATCH 1/5] Updating p4rt-ctl binary * Updating p4rt-ctl binary with 2024-08 from 2023-11 * Adding few files to gitignore * Updating p4runtime whl file in repo with 2024-08 * ipuplugin Dockerfile changes * Adding new builder stage for gRPC python building * cygrpc library being pulled has debug symbols adding 300MB so stripping them. * Moving ENV variables for proxy at top * Upgrading Base OS image from Alpine 3.19.1 to 3.19.4 Signed-off-by: Sayan Bandyopadhyay --- .gitignore | 6 + e2e/artefacts/bin/p4rt-ctl | 113 ++++++++++++++---- .../bin/p4runtime-2023.11.0-py3-none-any.whl | Bin 21190 -> 0 bytes .../bin/p4runtime-2024.8.0-py3-none-any.whl | Bin 0 -> 24286 bytes ipu-plugin/images/Dockerfile | 28 +++-- 5 files changed, 110 insertions(+), 37 deletions(-) delete mode 100644 e2e/artefacts/bin/p4runtime-2023.11.0-py3-none-any.whl create mode 100644 e2e/artefacts/bin/p4runtime-2024.8.0-py3-none-any.whl diff --git a/.gitignore b/.gitignore index bf6b1e5b..994b8208 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,9 @@ */build/* */bin/* */.gopath/* +*.tar.gz +*.swp +*.swo + + +ipu-plugin/p4-rh_mvp diff --git a/e2e/artefacts/bin/p4rt-ctl b/e2e/artefacts/bin/p4rt-ctl index 3b7707e9..d76e949e 100755 --- a/e2e/artefacts/bin/p4rt-ctl +++ b/e2e/artefacts/bin/p4rt-ctl @@ -1,6 +1,6 @@ #! /usr/bin/python3 # -# Copyright (c) 2021-2023 Intel Corporation. +# Copyright (c) 2021-2024 Intel Corporation. # # SPDX-License-Identifier: Apache-2.0 # @@ -44,6 +44,13 @@ from functools import wraps import google.protobuf.text_format from google.rpc import status_pb2, code_pb2 +try: + from idpf import p4info_pb2 as idpf_p4info + from idpf import p4runtime_pb2 as idpf_p4runtime +except: + print("Unable to import the 'idpf' modules. The meter commands will not work.\n" + "To fix the problem, install an updated version of the python p4runtime package.") + from p4.v1 import p4runtime_pb2 from p4.v1 import p4runtime_pb2_grpc from p4.config.v1 import p4info_pb2 @@ -78,6 +85,7 @@ for P4Runtime switches: add-meter-config SWITCH MTR_TBL MTR_FLOW add packet mod meter config table entry get-packet-mod-meter SWITCH MTR_TBL MTR_FLOW gets packet mod meter table entry get-direct-pkt-mod-meter SWITCH MTR_TBL MTR_FLOW gets direct packet mod meter table entry + del-meter-config SWITCH MTR_TBL MTR_FLOW delete packet mod meter config table entry """ def usage(): @@ -466,24 +474,25 @@ class P4InfoHelper(object): table_entry = p4runtime_pb2.TableEntry() table_entry.table_id = self.get_tables_id(table_name) - for mfn, value in match_fields.items(): - # A table can contain more than one match filed and in such cases - # if one match_type has ternary and other filed is of any type - # it is considered as ternary match_type. - # In these cases we expect priority field from the user. - p4info_match = self.get_match_field(table_name, mfn) - - if p4info_match.match_type == p4info_pb2.MatchField.TERNARY: - one_match_type_is_ternary = True - # If match_type is ternary, then priority field is expected - if priority == None: - print("For ternary match_type, priority field is needed") - sys.exit(1) - - if match_fields: - table_entry.match.extend([ - self.get_match_field_pb(table_name, mfn, value) - ]) + if match_fields: + for mfn, value in match_fields.items(): + # A table can contain more than one match field, and in such cases, + # if one match_type has ternary and other field is of any type, + # it is considered as ternary match_type. + # In these cases, we expect a priority field from the user. + p4info_match = self.get_match_field(table_name, mfn) + + if p4info_match.match_type == p4info_pb2.MatchField.TERNARY: + one_match_type_is_ternary = True + # If match_type is ternary, then priority field is expected + if priority is None: + print("For ternary match_type, priority field is needed") + sys.exit(1) + + if match_fields: + table_entry.match.extend([ + self.get_match_field_pb(table_name, mfn, value) + ]) if priority is not None and one_match_type_is_ternary: table_entry.priority = int(priority) @@ -588,8 +597,11 @@ class P4RuntimeClient: def __init__(self, device_id, grpc_addr='localhost:9559', election_id=(1, 0)): + global client_role_name + self.device_id = device_id self.election_id = election_id + self.role_name = client_role_name grpc_addr = str(grpc_server_addr) root_ca_file_path = '/usr/share/stratum/certs/ca.crt' @@ -662,6 +674,8 @@ class P4RuntimeClient: election_id = arbitration.election_id election_id.high = self.election_id[0] election_id.low = self.election_id[1] + if self.role_name is not None: + arbitration.role.name = self.role_name self.stream_out_q.put(req) rep = self.get_stream_packet("arbitration", timeout=2) @@ -728,6 +742,8 @@ class P4RuntimeClient: election_id = req.election_id election_id.high = self.election_id[0] election_id.low = self.election_id[1] + if self.role_name is not None: + req.role = self.role_name req.action = p4runtime_pb2.SetForwardingPipelineConfigRequest. \ VERIFY_AND_COMMIT with open(p4info_path, 'r') as f1: @@ -755,6 +771,8 @@ class P4RuntimeClient: election_id = req.election_id election_id.high = self.election_id[0] election_id.low = self.election_id[1] + if self.role_name is not None: + req.role = self.role_name return self.stub.Write(req) @parse_p4runtime_write_error @@ -764,6 +782,8 @@ class P4RuntimeClient: election_id = req.election_id election_id.high = self.election_id[0] election_id.low = self.election_id[1] + if self.role_name is not None: + req.role = self.role_name req.updates.extend([update]) return self.stub.Write(req) @@ -1239,8 +1259,10 @@ def p4ctl_mod_entry(client, bridge, tbl_name, flow): def p4ctl_set_default_entry(client, bridge, tbl_name, action): """ set-default-entry SWITCH TABLE ACTION - Example: - p4rt-ctl set-default-entry br0 pipe.filter_tbl pipe.push_mpls(10) + Example of setting to valid action: + p4rt-ctl set-default-entry br0 pipe.filter_tbl "pipe.push_mpls(10)" + Example of resetting to default action: + p4rt-ctl set-default-entry br0 pipe.filter_tbl "" """ p4info = client.get_p4info() @@ -1248,12 +1270,14 @@ def p4ctl_set_default_entry(client, bridge, tbl_name, action): raise Exception("cannot retrieve P4Info from device {}".format(bridge)) helper = P4InfoHelper(p4info) - action_name, action_data = parse_action(action) + action_name, action_data = parse_action(action, helper) te = helper.buildTableEntry( table_name=tbl_name, default_action=True, action_name=action_name, - action_params={a.name: int(action_data[idx]) for idx, + action_params=action_data + if (action_data==None or action_data==['']) + else {a.name: int(action_data[idx]) for idx, a in enumerate(helper.get_action_params(action_name))}) update = p4runtime_pb2.Update() @@ -1842,7 +1866,6 @@ def _format_me(ce): return output_buffer def _format_dme(ce): - pdb.set_trace() output_buffer = 'table_id={}'.format(ce.table_entry.table_id) output_buffer += ', direct_meter_counter_data_green=(bytes={},packets={})'.format(ce.counter_data.green.byte_count, ce.counter_data.green.packet_count) output_buffer += ', direct_meter_counter_data_yellow=(bytes={},packets={})'.format(ce.counter_data.yellow.byte_count, ce.counter_data.yellow.packet_count) @@ -1909,6 +1932,34 @@ def p4ctl_get_direct_pkt_mod_meter_entry(client, bridge, tbl_name, flow): if entity.direct_meter_entry.table_entry.table_id == ce.table_entry.table_id: print(_format_dme(entry.direct_meter_entry)) +@with_client +def p4ctl_del_meter_config(client, bridge, tbl_name, flow): + """ + del-meter-config SWITCH MTR_TBL MTR_FLOW + Example: + p4rt-ctl del-meter-config br0 my_control.meter1 "meter_id=2244878476,meter_index=10" + """ + p4info = client.get_p4info() + if not p4info: + raise Exception("cannot retrieve P4Info from device {}".format(bridge)) + + helper = P4InfoHelper(p4info) + entity = p4runtime_pb2.Entity() + ce = entity.meter_entry + + if ce is None: + raise Exception("Cannot find meter_entry field in entity") + + meter_id, index = parse_get_meter_flow(flow) + ce.index.index = int(index) + ce.meter_id = int(meter_id) + + update = p4runtime_pb2.Update() + update.type = p4runtime_pb2.Update.DELETE + update.entity.meter_entry.CopyFrom(ce) + + client.write_update(update) + all_commands = { "show": (p4ctl_show, 1), "set-pipe": (p4ctl_set_pipe, 3), @@ -1932,7 +1983,8 @@ all_commands = { "reset-counter" : (p4ctl_reset_counter_entry, 2), "add-meter-config" : (p4ctl_add_meter_config, 3), "get-packet-mod-meter" : (p4ctl_get_packet_mod_meter_entry, 2), - "get-direct-pkt-mod-meter" : (p4ctl_get_direct_pkt_mod_meter_entry, 2) + "get-direct-pkt-mod-meter" : (p4ctl_get_direct_pkt_mod_meter_entry, 2), + "del-meter-config" : (p4ctl_del_meter_config, 2) } @@ -1941,16 +1993,20 @@ def validate_args(argv, command, expected_nr): raise Exception("p4rt-ctl: '{}' command requires at least {} " "arguments".format(command, expected_nr)) -# Global variable +# Global variables grpc_server_addr = "" +client_role_name = None def main(): global grpc_server_addr + global client_role_name + if len(sys.argv) < 2: print("p4rt-ctl: missing command name; use --help for help") sys.exit(1) parser = argparse.ArgumentParser(usage=USAGE) parser.add_argument('-g', '--grpc_addr', required=False, type=str, help="P4Runtime gRPC server address, format : :") + parser.add_argument('-r', '--role_name', required=False, type=str, help="Role name of this client") parser.add_argument('command', nargs='*', help='Subcommand to run') args = parser.parse_args() if args.grpc_addr is None: @@ -1962,6 +2018,11 @@ def main(): else: print("Invalid IP address for GRPC server ") system.exit(1) + + # client_role_name will default to 'None' (global var) unless user sets + # a name using the args.role_name flag + client_role_name = args.role_name + if args.command[0] not in all_commands.keys(): usage() diff --git a/e2e/artefacts/bin/p4runtime-2023.11.0-py3-none-any.whl b/e2e/artefacts/bin/p4runtime-2023.11.0-py3-none-any.whl deleted file mode 100644 index 1bb524d01060e28fbffb6463d932f612b57182b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21190 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

{#lk*W!8!w3{smnznjQ9OyGj6eCRn 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 Date: Fri, 18 Oct 2024 08:45:55 -0400 Subject: [PATCH 2/5] Static analysis error --- ipu-plugin/images/Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ipu-plugin/images/Dockerfile b/ipu-plugin/images/Dockerfile index 626560e8..0c0f659b 100644 --- a/ipu-plugin/images/Dockerfile +++ b/ipu-plugin/images/Dockerfile @@ -1,13 +1,14 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Intel Corporation + +ARG TARGETOS +ARG TARGETARCH ENV HTTP_PROXY $http_proxy ENV HTTPS_PROXY $https_proxy FROM golang:1.22.5-alpine@sha256:0d3653dd6f35159ec6e3d10263a42372f6f194c3dea0b35235d72aabde86486e as builder -RUN apk add --no-cache git -ARG TARGETOS -ARG TARGETARCH +RUN apk add --no-cache git RUN apk add --no-cache --virtual build-dependencies build-base COPY . /usr/src/ipu-opi-plugin WORKDIR /usr/src/ipu-opi-plugin From 804678f9b2cf4855a56d98baded6975587dbc8f6 Mon Sep 17 00:00:00 2001 From: Sayan Bandyopadhyay Date: Fri, 18 Oct 2024 09:19:37 -0400 Subject: [PATCH 3/5] removing proxy settings from dockerfile --- ipu-plugin/images/Dockerfile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ipu-plugin/images/Dockerfile b/ipu-plugin/images/Dockerfile index 0c0f659b..e7a30030 100644 --- a/ipu-plugin/images/Dockerfile +++ b/ipu-plugin/images/Dockerfile @@ -1,15 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Intel Corporation - +# Apply environment +FROM golang:1.22.5-alpine@sha256:0d3653dd6f35159ec6e3d10263a42372f6f194c3dea0b35235d72aabde86486e as builder ARG TARGETOS ARG TARGETARCH -ENV HTTP_PROXY $http_proxy -ENV HTTPS_PROXY $https_proxy - -FROM golang:1.22.5-alpine@sha256:0d3653dd6f35159ec6e3d10263a42372f6f194c3dea0b35235d72aabde86486e as builder -RUN apk add --no-cache git RUN apk add --no-cache --virtual build-dependencies build-base +RUN apk add --no-cache git COPY . /usr/src/ipu-opi-plugin WORKDIR /usr/src/ipu-opi-plugin RUN go mod download From 15d2cf70554f43aa82e680ef89726e1d63ab369f Mon Sep 17 00:00:00 2001 From: Sayan Bandyopadhyay Date: Fri, 18 Oct 2024 10:12:02 -0400 Subject: [PATCH 4/5] more static fail fixes --- ipu-plugin/images/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ipu-plugin/images/Dockerfile b/ipu-plugin/images/Dockerfile index e7a30030..e58e6144 100644 --- a/ipu-plugin/images/Dockerfile +++ b/ipu-plugin/images/Dockerfile @@ -16,8 +16,9 @@ FROM python:3.11-alpine as builderpy COPY bin/p4runtime-2024.8.0-py3-none-any.whl /opt/p4/p4-cp-nws/bin/ RUN apk add -U --no-cache py3-pip'=='24.0-r2 \ g++ linux-headers python3-dev binutils +SHELL ["/bin/ash", "-o", "pipefail", "-c"] RUN python3 -m pip install --no-cache-dir /opt/p4/p4-cp-nws/bin/p4runtime-2024.8.0-py3-none-any.whl -RUN find /usr/local/lib/python3.11/site-packages/ -name "cygrpc*" | xargs strip --strip-debug +RUN find /usr/local/lib/python3.11/site-packages/ -name "cygrpc*" -print0 | xargs -0 strip --strip-debug FROM alpine:3.19.4 @@ -36,4 +37,4 @@ WORKDIR / LABEL io.k8s.display-name="IPU OPI Plugin" RUN rm -rf /var/cache/apk/* -RUN apk add --update --no-cache openssh +RUN apk add --update --no-cache openssh binutils From d30c20a17cfd0ca71f2873831a2503ecb0ae2041 Mon Sep 17 00:00:00 2001 From: Sayan Bandyopadhyay Date: Mon, 21 Oct 2024 13:25:39 -0400 Subject: [PATCH 5/5] Removing unnecessary comment and git install --- ipu-plugin/images/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ipu-plugin/images/Dockerfile b/ipu-plugin/images/Dockerfile index 8d03d3f5..495c59bf 100644 --- a/ipu-plugin/images/Dockerfile +++ b/ipu-plugin/images/Dockerfile @@ -1,12 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Intel Corporation -# Apply environment + FROM golang:1.22.5-alpine@sha256:0d3653dd6f35159ec6e3d10263a42372f6f194c3dea0b35235d72aabde86486e as builder ARG TARGETOS ARG TARGETARCH RUN apk add --no-cache --virtual build-dependencies build-base -RUN apk add --no-cache git COPY . /usr/src/ipu-opi-plugin WORKDIR /usr/src/ipu-opi-plugin RUN go mod download