p4lang / behavioral-model

The reference P4 software switch
Apache License 2.0
544 stars 330 forks source link

clone operation not working on simple_switch_grpc target #478

Closed dushyantarora13 closed 6 years ago

dushyantarora13 commented 6 years ago

I wrote a simple clone.p4 file:

#include <core.p4>
#include <v1model.p4>

struct H { };
struct M { };

parser ParserI(packet_in pk, out H hdr, inout M meta, inout standard_metadata_t smeta) {
    state start { transition accept; }
}

control IngressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
    apply {
        clone(CloneType.I2E, 1024);
    }
};

control EgressI(inout H hdr, inout M meta, inout standard_metadata_t smeta) {
    apply { }
};

control DeparserI(packet_out pk, in H hdr) {
    apply { }
}

control VerifyChecksumI(inout H hdr, inout M meta) {
    apply { }
}

control ComputeChecksumI(inout H hdr, inout M meta) {
    apply { }
}

V1Switch(ParserI(), VerifyChecksumI(), IngressI(), EgressI(),
         ComputeChecksumI(), DeparserI()) main;

and a corresponding test in targets/simple_switch_grpc/tests/

#include <grpc++/grpc++.h>

#include <p4/bm/dataplane_interface.grpc.pb.h>
#include <p4/p4runtime.grpc.pb.h>

#include <gtest/gtest.h>

#include <memory>
#include <string>

#include "base_test.h"

namespace sswitch_grpc {

namespace testing {

namespace {

constexpr char clone_json[] = TESTDATADIR "/clone.json";

class SimpleSwitchGrpcTest_GrpcDataplane : public SimpleSwitchGrpcBaseTest {
 protected:
  SimpleSwitchGrpcTest_GrpcDataplane()
      : SimpleSwitchGrpcBaseTest(""),
        dataplane_channel(grpc::CreateChannel(
            dp_grpc_server_addr, grpc::InsecureChannelCredentials())),
        dataplane_stub(p4::bm::DataplaneInterface::NewStub(
            dataplane_channel)) { }

  void SetUp() override {
    SimpleSwitchGrpcBaseTest::SetUp();
    update_json(clone_json);
  }

  std::shared_ptr<grpc::Channel> dataplane_channel{nullptr};
  std::unique_ptr<p4::bm::DataplaneInterface::Stub> dataplane_stub{nullptr};
};

TEST_F(SimpleSwitchGrpcTest_GrpcDataplane, SendAndReceive) {
  p4::bm::PacketStreamRequest request;
  request.set_device_id(device_id);
  request.set_port(9);
  request.set_packet(std::string(10, '\xab'));
  ClientContext context;
  auto stream = dataplane_stub->PacketStream(&context);
  stream->Write(request);
  p4::bm::PacketStreamResponse response;
  while(stream->Read(&response)) {
    std::cout << "Received packet:" << std::endl;
    std::cout << response.device_id() << std::endl;
    std::cout << response.port() << std::endl;
    std::cout << response.packet() << std::endl;
  }
  stream->WritesDone();
  auto status = stream->Finish();
  EXPECT_TRUE(status.ok());
}

}  // namespace

}  // namespace testing

}  // namespace sswitch_grpc

I get a single packet in my output instead of 2. I used clone3 as well with the same result.

qin-nz commented 6 years ago

Have you try use simple_switch_CLI or something else to add a mirroring port?

For example, you should using simple_switch_CLI to run following command. And you will get the cloned packet on port 10.

mirroring_add 1024 10
dushyantarora13 commented 6 years ago

Thanks for replying. I can only use P4Runtime commands to configure the switch (https://github.com/p4lang/PI/blob/master/proto/p4/p4runtime.proto). I don't see any message to add a mirroring port there. According to the declaration of clone in v1model.p4 the second argument is a session number: extern void clone(in CloneType type, in bit<32> session); I don't know what the expected value is for it.

qin-nz commented 6 years ago

@dushyantarora13 You are using the target independent way to configure switch. But mirroring_add is target dependent, that means mirroring_add is only suitable for target simple_switch (V1Switch). So you can't find it in p4runtime.

antoninbas commented 6 years ago

@dushyantarora13 there are 2 things to take into account:

  1. the p4c compiler may not be producing a correct bmv2 JSON file. It is hard for me to say without taking a look at the generated JSON. That would make it a compiler issue, not a bmv2 issue.
  2. as mentioned by @qin-nz, even if the JSON is correct, the cloning operation will not actually take place until you map the mirroring session id (in your case 1024) to an actual physical port. This requires a control-plane operation which is currently not supported by P4 Runtime - and it will likely never be supported as PSA does cloning differently, without the notion of mirroring session. Until the PSA architecture is finalized and bmv2-psa-grpc comes to life, I suggest you hack something up in your local clone of simple_switch_grpc to get cloning to work. If you want to support cloning to the CPU port, just add the following call to the runner's initialization routine: mirroring_mapping_add(1024, <your CPU port>).

Edit: It seems that PSA will actually introduce sessions for configuring cloning, which means P4 Runtime should support this in the near future.

dushyantarora13 commented 6 years ago

Thanks for the reply Antonin and qin-nz.