Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client changes for packetIO #321

Merged
merged 8 commits into from
Nov 9, 2023
Merged
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
77 changes: 77 additions & 0 deletions clients/p4rt-ctl/p4rt-ctl.in
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import struct
import sys
import threading
import time
import fcntl
import select
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When manifest is updated with this SHA, please update ACC scripts as well to include fcntl and select python packages

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

from functools import wraps

import google.protobuf.text_format
Expand Down Expand Up @@ -660,6 +662,26 @@ class P4RuntimeClient:
pass
return None

def get_packet_in(self, timeout=3):
msg = self.get_stream_packet("packet", timeout)
if msg is not None:
return msg.packet

def send_packet_out(self, payload):
packet_out = p4runtime_pb2.PacketOut()
packet_out.payload = payload
packet_out_req = p4runtime_pb2.StreamMessageRequest()
packet_out_req.packet.CopyFrom(packet_out)
self.stream_out_q.put(packet_out_req)

# Continuously poll for pkts from the server
def pktio_rx(self, tap_device):
print("Waiting for Rx packets...")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to have a print statement inside a continuous poll function? This will spam and slow down

Copy link
Collaborator Author

@satish153 satish153 Nov 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you asking about print("Waiting for Rx packets...")? This line is outside the while loop which checks for packets continuously.

Output of start-pktio looks like below:

[root@CP-1049136 ipdk_recipe]# $IPDK_RECIPE/install/bin/p4rt-ctl start-pktio
br0
Created TAP device pktioTap0
Tx thread polling on TAP port
Waiting for Rx packets...

while True:
pkt = self.get_packet_in()
if pkt is not None:
tap_device.write(pkt.payload)

@parse_p4runtime_error
def get_p4info(self):
req = p4runtime_pb2.GetForwardingPipelineConfigRequest()
Expand Down Expand Up @@ -769,6 +791,60 @@ def p4ctl_show(client, bridge):
def p4ctl_set_pipe(client, bridge, device_config, p4info):
client.set_fwd_pipe_config(p4info, device_config)

class TapDevice:
def __init__(self, tap_name):

self.tap_name = tap_name

# constants derived from
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/if_tun.h#L34
TUNSETIFF = 0x400454CA
satish153 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a macro to define these contstants instead and add a comment that it's from linux/if_tun.h? https://peps.python.org/pep-0591/

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment applicable for all the values below

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand, uppercase variable names are used to indicate that a variable's value should be treated as constant. I understand the variable is not truly immutable but that's the convention used to declare consts.

Thanks for the reference on using 'Final'. I now, learnt that there is a way to enforce immutability. However, it involves importing an additional module which might be a overkill in this specific case.

IFF_TAP = 0x0002
IFF_NO_PI = 0x1000
try:
self.tap = os.open("/dev/net/tun", os.O_RDWR)
satish153 marked this conversation as resolved.
Show resolved Hide resolved

# Configure the TAP interface.
ifr = struct.pack('16sH', self.tap_name.encode(), IFF_TAP | IFF_NO_PI)
fcntl.ioctl(self.tap, TUNSETIFF, ifr)

print(f"Created TAP device {self.tap_name}")
except Exception as e:
print(f"Error creating TAP interface: {e}")
if self.tap is not None:
os.close(self.tap)

# Continuously reads pkts from TAP port and sends them out to the server
def read(self, client):
MAX_FRAME_SIZE = 1500
SELECT_TIMEOUT = 0.1
while True:
readable, _, _ = select.select([self.tap], [], [], SELECT_TIMEOUT)
if self.tap in readable:
# read pkt from tap port
data = os.read(self.tap, MAX_FRAME_SIZE)

# send the packet to the server
client.send_packet_out(data)

# Sends pkts to the tap port
def write(self, data):
os.write(self.tap, data)

# Thread function to read pkts from TAP port
def read_from_tap(tap, client):
print("Tx thread polling on TAP port")
tap.read(client)

@with_client
def p4ctl_start_pktio(client, bridge):
try:
tap_device = TapDevice("pktioTap0")
tx_thread = threading.Thread(target=read_from_tap, args=(tap_device,client))
tx_thread.start()
client.pktio_rx(tap_device)
except Exception as e:
print(f"Error: Failed to start packetIo {e}")

@with_client
def p4ctl_get_pipe(client, bridge):
Expand Down Expand Up @@ -1611,6 +1687,7 @@ def p4ctl_reset_counter_entry(client, bridge, cnt_tbl_name, flow):
all_commands = {
"show": (p4ctl_show, 1),
"set-pipe": (p4ctl_set_pipe, 3),
"start-pktio": (p4ctl_start_pktio, 1),
"get-pipe": (p4ctl_get_pipe, 1),
"add-entry": (p4ctl_add_entry, 3),
"modify-entry": (p4ctl_mod_entry, 3),
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
p4runtime==1.3.0
fcntl
select