Purge table entries

Is there a way to purge table entries that are add via p4runtime?

I am looking for a way to delete a table entry with a specific priority value or based on some criteria.

Yes. If you check the P4Runtime specification:

9.1. TableEntry

(…)
The match and priority fields are used to uniquely identify an entry within a table. Therefore, these fields cannot be modified after the entry has been inserted and must be provided for MODIFY and DELETE updates.
(…)

12. Write RPC

(…)

message Update {
 enum Type {
  UNSPECIFIED = 0;
  INSERT = 1;
   MODIFY = 2;
   DELETE = 3;
 }
 Type type = 1;
 Entity entity = 2;
}

(…)

  • DELETE : Deletes the specified P4 entity. If the entity does not exist, a NOT_FOUND error is returned. In order to delete, the entity specification only needs to include the key. Any non-key parts of entity are ignored.

You can check an example from the P4Runtime-shell code:

# To delete all the entries from a table, simply use:
table_entry['<table_name>'].read(function=lambda x: x.delete())

# Read all entries and delete all - taken from README:
P4Runtime sh >>> for te in table_entry["FabricIngress.forwarding.routing_v4"].read():
            ...:     print(te)
P4Runtime sh >>> table_entry["FabricIngress.forwarding.routing_v4"].read(lambda te: te.delete())

or from the delete() function:

def delete(self):
    if self._modify_only:
        raise NotImplementedError("Delete not supported for {}".format(self._entity_type.name))
    logging.debug("Deleting entry")
    self._write(p4runtime_pb2.Update.DELETE)

IIf you need an example that is already working you can find any repository code that uses a DeleteTableEntry(), like this one:. I picked a rnadom example I saw on Github so I am sorry if the name of the tables and methods are confusing. Just focus on the libraries and methods used :slight_smile:

def writeVrfRules(delete, p4info_helper, ingress_sw, port, vrf):
    # You can add the priority as a parameter for buildTableEntry
    table_entry = p4info_helper.buildTableEntry(
        table_name="ig_ctl.ig_ctl_vrf.tbl_vrf",
        match_fields={
            "ig_md.source_id": port
        },
        action_name="ig_ctl.ig_ctl_vrf.act_set_vrf",
        # priority=1,
        action_params={
            "vrf": vrf
        })
    # some code
        ingress_sw.DeleteTableEntry(table_entry, False)

So you have to build a table entry that matches the one you want to remove and then call DeleteTableEntry. You will need a similar project structure as the one shown in this folder. DeleteTableEntry is located at switch.py, see here.

Trying to be a little more specific, if you check the main() of that same file (forwarder.py), you will see this line.

sw1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
      name='sw1',
      address=p4runtime_address,
      device_id=0,
      proto_dump_file='p4runtime-requests.txt')

sw1 includes the DeleteTableEntry method. When the controller calls writeVrfRules(), it passes sw1 as a parameter. Then writeVrfRules() calls DeleteTableEntry() as show in a previous example:

# from main
writeVrfRules(mode,p4info_helper,sw1,int(splt[1]),int(splt[2]))

# the method called
def writeVrfRules(delete, p4info_helper, ingress_sw, port, vrf):
    # some code
    # sw1 is renamed to ingress_sw
    ingress_sw.DeleteTableEntry(table_entry, False)