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

Add initial PTF tests for downlink and uplink #5

Merged
merged 7 commits into from
Apr 17, 2020
Merged

Conversation

badhrinathpa
Copy link
Contributor

No description provided.

@ccascone
Copy link
Contributor

ccascone commented Apr 14, 2020

Interestingly, tests failed but the status check is green. I will fix the status reporting. Here's the test error:

spgwu.GTPU_far_Test ... tcp ... ERROR

======================================================================
ERROR: spgwu.GTPU_far_Test
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./tests/spgwu.py", line 84, in runTest
    pkt_add_gtp(pkt, out_ipv4_src, out_ipv4_dst, src_teid)
NameError: global name 'pkt_add_gtp' is not defined

Copy link
Contributor

@ccascone ccascone left a comment

Choose a reason for hiding this comment

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

Test case LGTM. Comments are more about style.

Comment on lines 64 to 67
UDP_SRC_PORT = None
UDP_DST_PORT = None
PKT_SRC_IP = None
PKT_DST_IP = None
Copy link
Contributor

Choose a reason for hiding this comment

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

These variables get assigned as part of the test case, so they're not constants (as the case suggests). Let's remove them from here, and simply have (lower_case) variables as part of the test case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 115 to 118
UDP_SRC_PORT = self.inner_pkt[UDP].sport
UDP_DST_PORT = self.inner_pkt[UDP].dport
PKT_SRC_IP = self.inner_pkt[IP].src
PKT_DST_IP = self.inner_pkt[IP].dst
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's use lower case here, these are not constant values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 115 to 144
UDP_SRC_PORT = self.inner_pkt[UDP].sport
UDP_DST_PORT = self.inner_pkt[UDP].dport
PKT_SRC_IP = self.inner_pkt[IP].src
PKT_DST_IP = self.inner_pkt[IP].dst
'''
for teid, src_addr, dst_addr, src_port, dst_port, proto, pdr_id in \
zip([(src_teid, 0xffffffff),(0xfffff,0)], \
[(PKT_SRC_IP,IP_MASK), (PKT_DST_IP,IP_MASK)], \
[(PKT_DST_IP,IP_MASK), (PKT_DST_IP,IP_MASK)], \
[(UDP_SRC_PORT, UDP_SRC_PORT), (UDP_DST_PORT,UDP_DST_PORT)], \
[(UDP_DST_PORT, UDP_DST_PORT), (UDP_SRC_PORT, UDP_SRC_PORT)], \
#range still not sure how to write
[(IP_PROTO_UDP, 0xFF), (IP_PROTO_UDP, 0xFF)], \
[UL_PDR_ID, DL_PDR_ID]):
self.insert(self.helper.build_table_entry(
table_name="IngressPipeImpl.pdrs",
match_fields={
# Exact match.
"teid": teid,
"ue_addr": src_addr,
"inet_addr": dst_addr,
"ue_l4_port":src_port,
"inet_l4_port":dst_port,
"ip_proto":proto
},
action_name="IngressPipeImpl.set_pdr_id",
action_params={"id":pdr_id},
priority = 1
))
'''
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we remove this commented block?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

Comment on lines 95 to 97
#self.testPacket(pkt)

#pkt[IP].payload[IP]
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like these are leftover comments. Let's remove them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

Comment on lines 152 to 153
"ue_l4_port":(UDP_SRC_PORT, UDP_SRC_PORT),
"inet_l4_port":(UDP_DST_PORT, UDP_DST_PORT),
Copy link
Contributor

Choose a reason for hiding this comment

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

The same match value is used as mask. I think it should be all ones (16 bits for L4 ports, so 0xFFFF).

Copy link
Contributor

@ccascone ccascone Apr 15, 2020

Choose a reason for hiding this comment

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

Ops! my bad, I didn't realize we use range match for ports. I tought it was ternary. Please ignore my comment...

pkt_route(exp_pkt, next_hop_mac)
pkt_decrement_ttl(exp_pkt)
#exp_pkt = pkt.copy()
print self.port1
Copy link
Contributor

Choose a reason for hiding this comment

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

This print statement seems useful for debugging, perhaps it can be removed from the commit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

Comment on lines 43 to 45
SPGW_DIR_UNKNOWN = 0;
SPGW_DIR_UPLINK = 1;
SPGW_DIR_DOWNLINK = 2;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these used anywhere? I think there are other constants that are not used in the test cases. We should avoid declaring unused stuff which otherwise makes the code hard to read/confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not used. removed.

for pkt_type in ["udp"]:
print_inline("%s ... " % pkt_type)
pkt = getattr(testutils, "simple_%s_packet" % pkt_type)()
self.inner_pkt = pkt
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you could avoid using this class-level inner_pkt variable/attribute, as you are already passing pkt as an argument of self.testPacket()...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The expected packet is without the gtpu, outer ip and outer udp header. So, storing and using the inner_pkt as expected pkt. We were not able to handle packet access beyond the gtpu in the argument pkt.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. When possible I prefer the functional approach for tests (i.e., everything is a function argument, no class-level variables) to reduce the risk of ending up in spaghetti code as the tests evolve. It looks like you could be passing inner_pkt as an argument of self.testPacket() and invoke self.pkt_add_gtp() from within self.testPacket() after storing an unmmodified version of the packet. Here's a similar test that does pppoe encap for the bng case: https://github.com/opennetworkinglab/tassen/blob/master/ptf/tests/upstream.py#L115

))

# Add entry to pdr_rule_lookup
UDP_SRC_PORT = self.inner_pkt[UDP].sport
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as before, it's not clear to me why you need to define inner_pkt. Can't you use pkt from the function arguments?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above.


# Expected pkt should have routed MAC addresses and decremented hop
# limit (TTL).
exp_pkt = self.inner_pkt.copy()
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, you can use pkt instead of inner_pkt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same as above.

Copy link
Contributor

@ccascone ccascone left a comment

Choose a reason for hiding this comment

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

LGTM. I left some comments, but we can fix later.

UDP_HDR_SIZE = 8
GTP_HDR_SIZE = 8
IP_VERSION_4 = 4
out_ipv4_src = '192.168.0.202'
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks these are constants, so using the upper case is preferred

Comment on lines +62 to +66
def read_pkt_count_pre_qos_pdr(self, line_id):
return self.read_pkt_count("IngressPipeImpl.pre_qos_pdr_counter", line_id)

def read_byte_count_pre_qos_pdr(self, line_id):
return self.read_byte_count("IngressPipeImpl.pre_qos_pdr_counter", line_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

This helper is meant to be P4 program agnostic. We don't need to fix this now, but in general, methods that are program-specific should go in a separate class, e.g. a client class with multiple implementations for the different targets (one for bmv2, one for tofino, etc.). Then we can think of ways to plug one implementation or the other when running the test cases... it would be good to fix after tonight's meeting.

Comment on lines +87 to +113
def read_request(self, req):
entities = []
grpc_addr = testutils.test_param_get("grpcaddr")
channel = grpc.insecure_channel(grpc_addr)
stub = p4runtime_pb2_grpc.P4RuntimeStub(channel)
try:
for resp in stub.Read(req):
entities.extend(resp.entities)
except grpc.RpcError as e:
if e.code() != grpc.StatusCode.UNKNOWN:
raise e
raise P4RuntimeException(e)
return entities

def write_request(self, req, store=True):
rep = self._write(req)
if store:
self.reqs.append(req)
return rep

def get_new_write_request(self):
req = p4runtime_pb2.WriteRequest()
req.device_id = int(testutils.test_param_get("device_id"))
election_id = req.election_id
election_id.high = 0
election_id.low = self.election_id
return req
Copy link
Contributor

Choose a reason for hiding this comment

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

Methods that deal with P4Runtime RPCs should go in base_test.py. As a matter of fact, there's already a grpc channel and a method for write request there. This helper is for constructing P4Runtime messages from a given P4Info (i.e. using table/counter names instead of IDs)

for pkt_type in ["udp"]:
print_inline("%s ... " % pkt_type)
pkt = getattr(testutils, "simple_%s_packet" % pkt_type)()
self.inner_pkt = pkt
Copy link
Contributor

Choose a reason for hiding this comment

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

I see. When possible I prefer the functional approach for tests (i.e., everything is a function argument, no class-level variables) to reduce the risk of ending up in spaghetti code as the tests evolve. It looks like you could be passing inner_pkt as an argument of self.testPacket() and invoke self.pkt_add_gtp() from within self.testPacket() after storing an unmmodified version of the packet. Here's a similar test that does pppoe encap for the bng case: https://github.com/opennetworkinglab/tassen/blob/master/ptf/tests/upstream.py#L115

class GTPU_far_DOWNLINK_Test(P4RuntimeTest):
"""Tests GTPU routing"""

outer_pkt = None
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, no need to be class-level

"""Tests GTPU routing"""

inner_pkt = None
ulfseid = 1
Copy link
Contributor

Choose a reason for hiding this comment

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

If ulfseid is meant to be a constant, then it should go outside of this class and be upper case

"""Tests GTPU routing"""

outer_pkt = None
dlfseid = 2
Copy link
Contributor

Choose a reason for hiding this comment

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

same as before, this should go out of this class and be upper case, since it's used as a constant

@ccascone ccascone changed the title ptf_test Add initial PTF tests for downlink and uplink Apr 17, 2020
@ccascone ccascone merged commit 82386da into master Apr 17, 2020
@ccascone ccascone deleted the ptf_update branch April 17, 2020 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants