示例#1
0
    def setUp(self, grpc_addr, proto_txt_path):
        #BaseTest.setUp(self)
        self.device_id = 0

        # Setting up PTF dataplane
        #        self.dataplane = ptf.dataplane_instance
        #        self.dataplane.flush()

        self._swports = []
        #        for device, port, ifname in config["interfaces"]:
        #            self._swports.append(port)

        #        grpc_addr = testutils.test_param_get("grpcaddr")
        if grpc_addr is None:
            grpc_addr = 'localhost:50051'

        self.channel = grpc.insecure_channel(grpc_addr)
        self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)

        #        proto_txt_path = testutils.test_param_get("p4info")
        print "Importing p4info proto from", proto_txt_path
        self.p4info = p4info_pb2.P4Info()
        with open(proto_txt_path, "rb") as fin:
            google.protobuf.text_format.Merge(fin.read(), self.p4info)

        self.import_p4info_names()
        self.import_p4info_ids()

        # used to store write requests sent to the P4Runtime server, useful for
        # autocleanup of tests (see definition of autocleanup decorator below)
        self._reqs = []

        self.set_up_stream()
示例#2
0
 def __init__(self, name, address='127.0.0.1:50051', device_id=0):
     self.name = name
     self.address = address
     self.device_id = device_id
     self.p4info = None
     self.channel = grpc.insecure_channel(self.address)
     self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
示例#3
0
    def __init__(self,
                 p4info_helper,
                 sw_info,
                 p4_ingress,
                 p4_egress,
                 proto_dump_file=None):
        self.p4info_helper = p4info_helper
        self.sw_info = sw_info
        self.p4_ingress = p4_ingress
        self.p4_egress = p4_egress
        self.name = sw_info['name']
        self.device_id = sw_info['id']
        channel = grpc.insecure_channel(sw_info['grpc'])
        if proto_dump_file is not None:
            logger.info('Adding interceptor with file - [%s]', proto_dump_file)
            interceptor = GrpcRequestLogger(proto_dump_file)
            channel = grpc.intercept_channel(channel, interceptor)

        logger.info('Creating client stub to channel - [%s] at address - [%s]',
                    channel, self.sw_info['grpc'])
        self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(channel)
        self.requests_stream = IterableQueue()
        self.stream_msg_resp = self.client_stub.StreamChannel(
            iter(self.requests_stream))
        self.proto_dump_file = proto_dump_file

        self.digest_thread = Thread(target=self.receive_digests)
    def setUp(self):
        BaseTest.setUp(self)
        self._swports = []
        for device, port, ifname in config["interfaces"]:
            self._swports.append(port)

        grpc_addr = testutils.test_param_get("grpcaddr")
        if grpc_addr is None:
            grpc_addr = 'localhost:50051'

        self.device_id = int(testutils.test_param_get("device_id"))
        if self.device_id is None:
            self.fail("Device ID is not set")

        self.cpu_port = int(testutils.test_param_get("cpu_port"))
        if self.cpu_port is None:
            self.fail("CPU port is not set")

        self.device = testutils.test_param_get("device")
        if self.device is None:
            self.fail("Device is not set")

        pltfm = testutils.test_param_get("pltfm")
        if pltfm is not None and pltfm == 'hw' and getattr(
                self, "_skip_on_hw", False):
            raise SkipTest("Skipping test in HW")

        proto_txt_path = testutils.test_param_get("p4info")
        # print "Importing p4info proto from", proto_txt_path
        self.p4info = p4info_pb2.P4Info()
        with open(proto_txt_path, "rb") as fin:
            google.protobuf.text_format.Merge(fin.read(), self.p4info)

        self.import_p4info_names()

        # used to store write requests sent to the P4Runtime server, useful for
        # autocleanup of tests (see definition of autocleanup decorator below)
        self.reqs = []

        self.election_id = 1
        if testutils.test_param_get("generate_tv") == 'True':
            self.generate_tv = True
        else:
            self.generate_tv = False
        if self.generate_tv:
            self.tv_list = []
            self.tv_name = self.__class__.__name__
        else:
            # Setting up PTF dataplane
            self.dataplane = ptf.dataplane_instance
            self.dataplane.flush()
            self.channel = grpc.insecure_channel(grpc_addr)
            self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
            self.set_up_stream()
示例#5
0
 def __init__(self, device_id, grpc_addr, election_id):
     self.device_id = device_id
     self.election_id = election_id
     logging.debug("Connecting to device {} at {}".format(device_id, grpc_addr))
     try:
         self.channel = grpc.insecure_channel(grpc_addr)
     except Exception:
         logging.critical("Failed to connect to P4Runtime server")
         sys.exit(1)
     self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
     self.stream_recv_handlers = []
     self.set_up_stream()
示例#6
0
    def __init__(self, name, address='127.0.0.1:50051', device_id=0, type='bmv2', crypto_address = None, debug=False):
        self.name = name
        self.address = address
        self.device_id = device_id
        self.p4info = None
        self.channel = grpc.insecure_channel(self.address)
        self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
        self.type = type
        self.crypto_client = None
        if self.type == 'tofino':
            self.crypto_client = TofinoCryptoClient(crypto_address)
        self.debug = debug
	self.request_lock = threading.Lock()
示例#7
0
    def __init__(self, device_id, grpc_addr, election_id):
        self.device_id = device_id
        self.election_id = election_id
        self.grpc_addr = grpc_addr
        logger.debug("Connecting to device {} at {}".format(device_id, grpc_addr))

        try:
            self.channel = grpc.insecure_channel(grpc_addr)
        except Exception:
            logger.critical("Failed to connect to P4Runtime server")
            sys.exit(1)
        self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
        return
示例#8
0
    def __init__(self):
        self.host = ServerConfig.HOST
        self.server_port = ServerConfig.SERVER_PORT
        self.device_id = 0

        with open(ServerConfig.SERVER_CERTIFICATE, "rb") as file:
            trusted_certs = file.read()

        self.credentials = grpc.ssl_channel_credentials(
            root_certificates=trusted_certs)
        self.channel = grpc.secure_channel(
            "{}:{}".format(self.host, self.server_port), self.credentials)
        self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
示例#9
0
文件: switch.py 项目: p4vbox/vIFC
 def __init__(self, name=None, address='127.0.0.1:50051', device_id=0,
              proto_dump_file=None):
     self.name = name
     self.address = address
     self.device_id = device_id
     self.p4info = None
     self.channel = grpc.insecure_channel(self.address)
     if proto_dump_file is not None:
         interceptor = GrpcRequestLogger(proto_dump_file)
         self.channel = grpc.intercept_channel(self.channel, interceptor)
     self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
     self.requests_stream = IterableQueue()
     self.stream_msg_resp = self.client_stub.StreamChannel(iter(self.requests_stream))
     self.proto_dump_file = proto_dump_file
     connections.append(self)
示例#10
0
    def __init__(self):
        # Configure the host and the port to which the client should connect to.
        self.host = ServerConfig.HOST
        self.server_port = ServerConfig.SERVER_PORT

        with open(ServerConfig.SERVER_CERTIFICATE, "rb") as file:
            trusted_certs = file.read()

        # Instantiate a communication channel and bind the client to the server.
        self.credentials = grpc.ssl_channel_credentials(root_certificates=trusted_certs)
        self.channel = grpc.secure_channel("{}:{}".format(self.host, self.server_port), self.credentials)
        self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)

        self.streamChannelRequest = p4runtime_pb2.StreamMessageRequest()
        self.sendRequest = True
    def __init__(self, sw_info, p4_ingress, p4_egress, proto_dump_file=None):
        super(P4RuntimeSwitch, self).__init__(sw_info)
        p4info_txt = sw_info['runtime_p4info']
        logger.info('Loading p4info_helper with file - [%s]', p4info_txt)
        self.p4info_helper = helper.P4InfoHelper(p4info_txt)
        self.p4_ingress = p4_ingress
        self.p4_egress = p4_egress
        grpc_channel = grpc.insecure_channel(self.grpc_addr)
        if proto_dump_file is not None:
            logger.info('Adding interceptor with file - [%s] to device [%s]',
                        proto_dump_file, self.grpc_addr)
            interceptor = GrpcRequestLogger(proto_dump_file)
            grpc_channel = grpc.intercept_channel(grpc_channel, interceptor)

        logger.info('Creating client stub to channel - [%s] at address - [%s]',
                    grpc_channel, self.grpc_addr)
        self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(grpc_channel)
        self.requests_stream = IterableQueue()
        self.stream_msg_resp = self.client_stub.StreamChannel(
            iter(self.requests_stream))
        self.proto_dump_file = proto_dump_file
        self.digest_thread = Thread(target=self.receive_digests)
示例#12
0
def update_config(config_path, p4info_path, grpc_addr, device_id):
    '''
    Performs a SetForwardingPipelineConfig on the device with provided
    P4Info and binary device config
    '''
    channel = grpc.insecure_channel(grpc_addr)
    stub = p4runtime_pb2_grpc.P4RuntimeStub(channel)
    print("Sending P4 config")
    request = p4runtime_pb2.SetForwardingPipelineConfigRequest()
    request.device_id = device_id
    config = request.config
    with open(p4info_path, 'r') as p4info_f:
        google.protobuf.text_format.Merge(p4info_f.read(), config.p4info)
    with open(config_path, 'rb') as config_f:
        config.p4_device_config = config_f.read()
    request.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT
    try:
        response = stub.SetForwardingPipelineConfig(request)
    except Exception as e:
        print("Error during SetForwardingPipelineConfig")
        print(str(e))
        return False
    return True
示例#13
0
    def __init__(self, device_id, grpc_addr, election_id, role_name=None, ssl_options=None):
        self.device_id = device_id
        self.election_id = election_id
        self.role_name = role_name
        if ssl_options is None:
            self.ssl_options = SSLOptions(True)
        else:
            self.ssl_options = ssl_options
        logging.debug("Connecting to device {} at {}".format(device_id, grpc_addr))
        if self.ssl_options.insecure:
            try:
                logging.debug("Using insecure channel")
                self.channel = grpc.insecure_channel(grpc_addr)
            except Exception:
                logging.critical("Failed to connect to P4Runtime server")
                sys.exit(1)
        else:
            # root certificates are retrieved from a default location chosen by gRPC runtime unless
            # the user provides custom certificates.
            root_certificates = None
            if self.ssl_options.cacert is not None:
                root_certificates = read_pem_file(self.ssl_options.cacert)
            certificate_chain = None
            if self.ssl_options.cert is not None:
                certificate_chain = read_pem_file(self.ssl_options.cert)
            private_key = None
            if self.ssl_options.key is not None:
                private_key = read_pem_file(self.ssl_options.key)
            creds = grpc.ssl_channel_credentials(root_certificates, private_key, certificate_chain)
            try:
                self.channel = grpc.secure_channel(grpc_addr, creds)
            except Exception:
                logging.critical("Failed to connect to P4Runtime server")
                sys.exit(1)

        self.stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
        self.set_up_stream()
示例#14
0
    def __init__(self, name=None, address='127.0.0.1:50051', device_id=0,
                 proto_dump_file=None):
        self.name = name
        self.address = address
        self.device_id = device_id
        self.p4info = None
        self.channel = grpc.insecure_channel(self.address)
        if proto_dump_file is not None:
            interceptor = GrpcRequestLogger(proto_dump_file)
            self.channel = grpc.intercept_channel(self.channel, interceptor)

        self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)

        self.proto_dump_file = proto_dump_file
        self.stream_out_q = IterableQueue()
        self.stream_in_q = IterableQueue()

        self.stream = self.client_stub.StreamChannel(self.stream_req_iterator())
        self.stream_recv_thread = threading.Thread(
            target=self.stream_recv, args=(self.stream,))

        self.active = True

        connections.append(self)
示例#15
0
    def __init__(self,
                 name=None,
                 address="127.0.0.1:50051",
                 device_id=0,
                 p4info_file_path=None,
                 proto_dump_file=None,
                 p4configjson=None,
                 toFlowID=0xffff0000,
                 queueDepth=1000,
                 queueRate=1000,
                 thriftPort=9090,
                 controlPlaneDelay=0):
        self.name = name
        self.toFlowID = toFlowID
        self.address = address
        self.device_id = device_id
        self.swNum = device_id + 1
        self.p4info = None
        self.bmv2_json_file_path = NotImplemented  # set this at programming time
        self.p4info_file_path = p4info_file_path
        self.p4info_helper = p4runtime_lib_helper.P4InfoHelper(
            p4info_file_path)
        self.channel = grpc.insecure_channel(self.address)
        if proto_dump_file is not None:
            interceptor = GrpcRequestLogger(proto_dump_file)
            self.channel = grpc.intercept_channel(self.channel, interceptor)
        self.client_stub = p4runtime_pb2_grpc.P4RuntimeStub(self.channel)
        self.proto_dump_file = proto_dump_file
        self.p4configjson = p4configjson
        ## below is from me:
        self.stop = False
        self.defaultRules = []
        self.activePorts = {}
        self.activePorts[1] = 0
        self.inactivePorts = []
        self.activeServices = {}
        self.master = False
        self.stream_out_q = Queue()
        self.qlogfile = open('logs/' + str(self.device_id) + '.log', "w+")
        self.qlogfileFirst = False
        self.numdigest = 0
        self.vnfList = []
        self.services = []
        self.flowRates = {}
        self.queueDepth = queueDepth
        self.thriftPort = thriftPort
        self.queueRate = queueRate
        self.overloadDetected = False
        self.migThreads = []
        self.controlPlaneDelay = controlPlaneDelay
        self.overloading = 0

        def stream_req_iterator():
            while True:
                p = self.stream_out_q.get()
                if p is None:
                    break
                yield p

        def stream_recv(self):
            i = 0
            #pr = cProfile.Profile()
            for msg in self.stream:
                tStart = time()
                if msg.HasField('packet'):
                    if msg.packet.payload.encode(
                            'hex')[0:4] == '3341' or msg.packet.payload.encode(
                                'hex')[0:4] == '3143':
                        #print msg.packet.payload.encode('hex') + ' recevied from ' + str(self.name)
                        if (msg.packet.payload.encode('hex')[20] == str(
                                self.swNum) and
                            (msg.packet.payload.encode('hex')[0:4] == '3341')):
                            # this packet is a sync thing received from a migration source:
                            #print msg.packet.payload.encode('hex')
                            migThread = threading.Thread(target=self.doCPSYnc,
                                                         args=(msg, ))
                            migThread.start()
                        else:
                            migThread = threading.Thread(
                                target=self.processMigPkt, args=(msg, ))
                            migThread.start()
                        #print "processing migpacket took %f seconds"% float(time() - tStart)
                    else:
                        pkt = controlPacket.controlPacket(msg,
                                                          self.name,
                                                          ts=float(tStart))
                        # # break if no valid ethtype can be derived
                        if hasattr(pkt.eth, 'type') and pkt.eth != None:
                            discList = [0xffff, 0xffee, 0xeffe]
                            ignoreList = [0x86dd, 0x0806]
                            if pkt.eth.type in discList:
                                thread = threading.Thread(
                                    target=self.processDiscPacket,
                                    args=(pkt, ))
                                thread.start()
                                continue
                            elif hex(pkt.eth.type
                                     ) not in ignoreList and pkt.ip != None:
                                thread = threading.Thread(
                                    target=self.processpacketIn, args=(pkt, ))
                                thread.start()
                elif msg.HasField('arbitration'):
                    print('arbitration packet recieved!')
                    if not msg.arbitration.status.message == "Is master":
                        print('Error setting controller as master for device')
                    else:
                        self.master = True
                elif msg.HasField('digest'):
                    # Digest message received. Send digestACK back:
                    self.digestMessageACK(msg.digest.digest_id,
                                          msg.digest.list_id)
                    self.numdigest += 1
                    digFields = self.p4info_helper.get_digest_fields_by_id(
                        msg.digest.digest_id)
                    # convert message to json format:
                    dictMsg = google.protobuf.json_format.MessageToDict(msg)
                    # read information to a dictionary:
                    infoDict = {}
                    printVals = []
                    printHdrs = []
                    enq_qdepth = None
                    deq_qdepth = None
                    deq_timedelta = None
                    threshold = None
                    timestamp = None
                    flowID = None
                    numPackets = None
                    enq_timestamp = None
                    for x in range(0, len(digFields)):
                        for y in digFields[x]:
                            infoDict[y] = {}
                            infoDict[y]['value'] = int(
                                bytes(
                                    base64.decodestring(
                                        dictMsg['digest']['data'][0]['struct']
                                        ['members'][x]['bitstring'])).encode(
                                            'hex'), 16)
                            infoDict[y]['bitlength'] = digFields[x][y]
                            if self.qlogfileFirst == False:
                                printHdrs.append(str(y))
                            printVals.append(infoDict[y]['value'])
                            if False == True:
                                print '%s, (%i bit): %i' % (
                                    y, infoDict[y]['bitlength'],
                                    infoDict[y]['value'])
                            # save values
                            if str(y) == str('enq_qdepth'):
                                enq_qdepth = infoDict[y]['value']
                            if str(y) == str('deq_qdepth'):
                                deq_qdepth = infoDict[y]['value']
                            if str(y) == str('deq_timedelta'):
                                deq_timedelta = float(
                                    infoDict[y]['value']) / float(
                                        1000000)  # convert to ms
                            if str(y) == str('threshold'):
                                threshold = infoDict[y]['value']
                            if str(y) == str('timestamp'):
                                timestamp = infoDict[y]['value']
                            if str(y) == str('flowID'):
                                flowID = infoDict[y]['value']
                            if str(y) == str('numPackets'):
                                numPackets = infoDict[y]['value']
                            if str(y) == str('enq_timestamp'):
                                enq_timestamp = infoDict[y]['value']

                    if enq_qdepth != None and deq_qdepth != None and deq_timedelta != None and enq_timestamp != None:
                        # print 'SWITCH OVERLOADING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
                        # print "enq_qdepth %s" % enq_qdepth
                        # print "deq_qdepth %s" % deq_qdepth
                        # print "deq_timedelta %s" % deq_timedelta

                        # figure out what to do
                        # create a thread that runs the checks for migration and initializes the migration.
                        # runMigration = False
                        # if self.overloadDetected == False:
                        #     runMigration = True
                        # # try:
                        # #     if (time() - float(self.overloadDetected)) > float(10):
                        # #         runMigration = True
                        # # except:
                        # #     pass

                        t = threading.Thread(target=pktMon.addpktDigestReading,
                                             args=(self.name, enq_qdepth,
                                                   deq_qdepth, deq_timedelta,
                                                   enq_timestamp))
                        t.start()
                        #print 'enqdepth: %i, deqdepth:%i' % (enq_qdepth, deq_qdepth)

                        if (enq_qdepth < deq_qdepth) and (deq_qdepth > 20):
                            #print "enqQdepth: %f deqQdepth: %f" %(float(enq_qdepth), float(deq_qdepth))
                            # NO SCALING IF CONTINUE BELOW HERE!
                            #continue
                            if self.overloadDetected == False:  # and self.overloading > 5:
                                self.overloadDetected = tStart
                                migrateThread = threading.Thread(
                                    target=flowHandler.migrationHandler,
                                    args=(self, enq_timestamp))
                                migrateThread.start()
                                print('Switch %s overloading!!!!' % self.name)

                        # Start the procedure to redirect the load to an other switch (if possible).
                        # if no solution exists, a new hardware switch should be added.

                        # This can be a problem....
                    elif threshold != None and timestamp != None and flowID != None and numPackets != None:
                        # this is a packet for rates....
                        t = threading.Thread(target=flowMonitor.addReading,
                                             args=(flowID, timestamp,
                                                   numPackets, self))
                        t.start()
                        #flowMonitor.addReading(flowID, timestamp, numPackets, self)
                        #print "%i/%i at timestamp %i for flowID %s from switch %s" % (numPackets, threshold, timestamp, flowID, self.name)
                    else:
                        print ' begin hellup'
                        if enq_qdepth == None:
                            print 'enq_qdepth is none'
                        if deq_qdepth == None:
                            print 'deq_qdepth is none'
                        if deq_timedelta == None:
                            print 'deq_timedelta is none'
                        print ' eind hellup'
                    # # writ things to file
                    # if self.qlogfileFirst == False:
                    #     self.qlogfile.write(str(printHdrs) + '\n')
                    #     self.qlogfileFirst = True

                    # self.qlogfile.write(str(printVals) + '\n')
                else:
                    print('unknown packet received')
                # has completed successfully
                tElapsed = time() - tStart
                #print("Elapsed time for packetin/out: %.20f ms" %(tElapsed * 1000))

        self.stream = self.client_stub.StreamChannel(stream_req_iterator())
        self.stream_recv_thread = threading.Thread(target=stream_recv,
                                                   args=(self, ))
        self.stream_recv_thread.start()

        # send masterarbitrationupdate:
        req = p4runtime_pb2.StreamMessageRequest()
        arbitration = req.arbitration
        arbitration.device_id = self.device_id
        arbitration.election_id.high = 0
        arbitration.election_id.low = 1
        self.stream_out_q.put(req)
        switchFinder.addSwitch(self)
示例#16
0
def update_config(p4info_path, bmv2_json_path, grpc_addr, device_id):
    """
    Performs a SetForwardingPipelineConfig on the device
    """
    channel = grpc.insecure_channel(grpc_addr)
    stub = p4runtime_pb2_grpc.P4RuntimeStub(channel)

    debug("Sending P4 config")

    # Send master arbitration via stream channel
    # This should go in library, to be re-used also by base_test.py.
    stream_out_q = Queue.Queue()
    stream_in_q = Queue.Queue()

    def stream_req_iterator():
        while True:
            p = stream_out_q.get()
            if p is None:
                break
            yield p

    def stream_recv(stream):
        for p in stream:
            stream_in_q.put(p)

    def get_stream_packet(type_, timeout=1):
        start = time.time()
        try:
            while True:
                remaining = timeout - (time.time() - start)
                if remaining < 0:
                    break
                msg = stream_in_q.get(timeout=remaining)
                if not msg.HasField(type_):
                    continue
                return msg
        except:  # timeout expired
            pass
        return None

    stream = stub.StreamChannel(stream_req_iterator())
    stream_recv_thread = threading.Thread(target=stream_recv, args=(stream, ))
    stream_recv_thread.start()

    req = p4runtime_pb2.StreamMessageRequest()
    arbitration = req.arbitration
    arbitration.device_id = device_id
    election_id = arbitration.election_id
    election_id.high = 0
    election_id.low = 1
    stream_out_q.put(req)

    rep = get_stream_packet("arbitration", timeout=5)
    if rep is None:
        error("Failed to establish handshake")
        return False

    try:
        # Set pipeline config.
        request = p4runtime_pb2.SetForwardingPipelineConfigRequest()
        request.device_id = device_id
        election_id = request.election_id
        election_id.high = 0
        election_id.low = 1
        config = request.config
        with open(p4info_path, 'r') as p4info_f:
            google.protobuf.text_format.Merge(p4info_f.read(), config.p4info)
        config.p4_device_config = build_bmv2_config(bmv2_json_path)
        request.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT
        try:
            stub.SetForwardingPipelineConfig(request)
        except Exception as e:
            error("Error during SetForwardingPipelineConfig")
            error(str(e))
            return False
        return True
    finally:
        stream_out_q.put(None)
        stream_recv_thread.join()
示例#17
0
def update_config(p4info_path,
                  bmv2_json_path,
                  tofino_bin_path,
                  tofino_cxt_json_path,
                  grpc_addr,
                  device_id,
                  generate_tv=False):
    """
    Performs a SetForwardingPipelineConfig on the device
    """
    # Build pipeline config request
    request = p4runtime_pb2.SetForwardingPipelineConfigRequest()
    request.device_id = device_id
    election_id = request.election_id
    election_id.high = 0
    election_id.low = 1
    config = request.config
    with open(p4info_path, 'r') as p4info_f:
        google.protobuf.text_format.Merge(p4info_f.read(), config.p4info)
    if bmv2_json_path is not None:
        device_config = build_bmv2_config(bmv2_json_path)
    else:
        device_config = build_tofino_config("name", tofino_bin_path,
                                            tofino_cxt_json_path)
    config.p4_device_config = device_config
    request.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT

    if generate_tv:
        # Create new target proto object for testvectors
        if bmv2_json_path is not None:
            tv_target = targetutils.get_new_target(grpc_addr, target_id="bmv2")
        else:
            tv_target = targetutils.get_new_target(grpc_addr,
                                                   target_id="tofino")
        # Write the target proto object to testvectors/target.pb.txt
        targetutils.write_to_file(tv_target, os.getcwd())
        # Create new testvector for set pipeline config and write to testvectors/PipelineConfig.pb.txt
        tv = tvutils.get_new_testvector()
        tv_name = "PipelineConfig"
        tc = tvutils.get_new_testcase(tv, tv_name)
        tvutils.add_pipeline_config_operation(tc, request)
        tvutils.write_to_file(tv, os.getcwd(), tv_name)
        return True
    channel = grpc.insecure_channel(grpc_addr)
    stub = p4runtime_pb2_grpc.P4RuntimeStub(channel)

    info("Sending P4 config")

    # Send master arbitration via stream channel
    # This should go in library, to be re-used also by base_test.py.
    stream_out_q = Queue.Queue()
    stream_in_q = Queue.Queue()

    def stream_req_iterator():
        while True:
            p = stream_out_q.get()
            if p is None:
                break
            yield p

    def stream_recv(stream):
        for p in stream:
            stream_in_q.put(p)

    def get_stream_packet(type_, timeout=1):
        start = time.time()
        try:
            while True:
                remaining = timeout - (time.time() - start)
                if remaining < 0:
                    break
                msg = stream_in_q.get(timeout=remaining)
                if not msg.HasField(type_):
                    continue
                return msg
        except:  # timeout expired
            pass
        return None

    stream = stub.StreamChannel(stream_req_iterator())
    stream_recv_thread = threading.Thread(target=stream_recv, args=(stream, ))
    stream_recv_thread.start()

    req = p4runtime_pb2.StreamMessageRequest()
    arbitration = req.arbitration
    arbitration.device_id = device_id
    election_id = arbitration.election_id
    election_id.high = 0
    election_id.low = 1
    stream_out_q.put(req)

    rep = get_stream_packet("arbitration", timeout=5)
    if rep is None:
        error("Failed to establish handshake")
        return False

    try:
        try:
            stub.SetForwardingPipelineConfig(request)
        except Exception as e:
            error("Error during SetForwardingPipelineConfig")
            error(str(e))
            return False
        return True
    finally:
        stream_out_q.put(None)
        stream_recv_thread.join()