Transport table debug information to controller

This commit is contained in:
Nico Schottelius 2019-03-25 13:43:47 +01:00
parent e1146070c4
commit 9ca4d4c8de
4 changed files with 88 additions and 26 deletions

View file

@ -422,7 +422,24 @@ Problem: task field might be overriden for controller use in different
table -> need different task field!
***** try2: checksum ok, but no packets on h3
****** Setup a default rule for the IPv4 world to debug on controller
****** DONE Setup a default rule for the IPv4 world to debug on controller
Still not seeing the converted packet, however seeing icmp6_ns packets
which should not be there:
table entry for ns:
ff:02:00:00:00:00:00:00:00:00:00:01:ff:00:00:42/128
debug packet seen in controller:
DEBUG:main:v6 reassambled=<Ether dst=33:33:ff:00:00:42 src=00:00:0a:00:00:01 type=0x86dd |<IPv6 version=6 tc=0 fl=0 plen=32 nh=ICMPv6 hlim=255 src=fe80::200:aff:fe00:1 dst=ff02::1:ff00:42 |<ICMPv6ND_NS type=Neighbor Solicitation code=0 cksum=0x37df res=0 tgt=2001:db8::42 |<ICMPv6NDOptSrcLLAddr type=1 len=1 lladdr=00:00:0a:00:00:01 |>>>>
DEBUG:main:v6 reassambled=<Ether dst=33:33:ff:00:00:42 src=00:00:0a:00:00:01 type=0x86dd |<IPv6 version=6 tc=0 fl=0 plen=32 nh=ICMPv6 hlim=255 src=fe80::200:aff:fe00:1 dst=ff02::1:ff00:42 |<ICMPv6ND_NS type=Neighbor Solicitation code=0 cksum=0x37df res=0 tgt=2001:db8::42 |<ICMPv6NDOptSrcLLAddr type=1 len=1 lladdr=00:00:0a:00:00:01 |>>>>
DEBUG:main:v6 reassambled=<Ether dst=33:33:ff:00:00:42 src=00:00:0a:00:00:01 type=0x86dd |<IPv6 version=6 tc=0 fl=0 plen=32 nh=ICMPv6 hlim=255 src=2001:db8::1 dst=ff02::1:ff00:42 |<ICMPv6ND_NS type=Neighbor Solicitation code=0 cksum=0x13a7 res=0 tgt=2001:db8::42 |<ICMPv6NDOptSrcLLAddr type=1 len=1 lladdr=00:00:0a:00:00:01 |>>>>
DEBUG:main:v6 reassambled=<Ether dst=00:00:0a:00:00:42 src=00:00:0a:00:00:01 type=0x86dd |<IPv6 version=6 tc=0 fl=920946 plen=64 nh=ICMPv6 hlim=64 src=2001:db8::1 dst=2001:db8:1::a00:1 |<ICMPv6EchoRequest type=Echo Request code=0 cksum=0xf981 id=0x5f7c seq=0x1 data='N\xc6\x98\\\x00\x00\x00\x00\x12\x1b\t\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567' |>>>
debugging MIGHT come from nat64 table!
*** TODO Get p4 VM / vagrant running
**** DONE install libvirtd-daemon
@ -1219,8 +1236,8 @@ debug packets - analyse code - goto 1
[21:26] line:~% sudo apt install thrift-compiler
libnanomsg-dev libjudy-dev
*** Performance comparison
*** Feature/Functionality difference / overview / CHALLENGES / LIMITATIONS in P4
**** P4: cannot read key from table
*** Challenges / Limitations in P4
**** DONE cannot read key from table
***** log
Key and mask for matching destination is in table. We need this
information in the action. However this information is not exposed, so
@ -1285,7 +1302,7 @@ Need to duplicate information
**** DONE ICMP6: checksum over payload
- variable length, up to 65k
Exists!
**** Synchronisation with the controller
**** DONE Synchronisation with the controller
- Double data type definition -> might differ
- TYPE_CPU for ethernet
- Port ingress offset (9 vs. 16 bit)
@ -1315,18 +1332,29 @@ Code:
}
#+END_SRC
**** (current) Implementation limitations
***** No fragmentation support (yet)
***** No session handling (yet)
**** No table meta information for default actions (asked 2019-03-25)
Is there any meta information for "from which table was the action
called" available? My use case is having a debug action that sends
packets to the controller and I use it as a default_action in various
tables; however know I don't know anymore from which table the action
was called. Is there any kind of meta information which table called
me available?
I could work around this by using if(! .. .hit) { my_action(table_id)
}, but it would not work with using default_action = ...
*** Implementation limitations
**** No fragmentation support (yet)
**** No session handling (yet)
1:1 mappings. No (automatic) session.
***** IPv4 / IPv6 embedding
**** IPv4 / IPv6 embedding
Currently offset based - probably not following the RFC!
***** No DNS64
**** No DNS64
has already been solved in a different domain - could even do
transparent / in network modification
***** Incomplete NDP
Very limited option support
***** NAT64 mappings not source network dependent
**** Incomplete NDP
Very limited option support
**** NAT64 mappings not source network dependent
Only the destination network is matched for deciding on NAT64, as
priority based double LPM is not supported. This limits a prefix to be
used only in one network.

View file

@ -23,11 +23,20 @@ log = logging.getLogger("main")
cpu_fields = {
0: 'UNSET',
1: 'ICMP6_NS',
2: 'ICMP6_GENERAL',
3: 'DEBUG'
}
table_id_fields = {
0: 'UNSET_TABLE',
1: 'TABLE_NAT64',
2: 'TABLE_ICMP6,
3: 'TABLE_V6_NETWORKS,
4: 'TABLE_NAT46',
5: 'TABLE_V4_NETWORKS'
}
class CpuHeader(Packet):
name = 'CpuPacket'
@ -35,6 +44,7 @@ class CpuHeader(Packet):
ShortEnumField('task', 1, cpu_fields ),
ShortField('ingress_port', 0),
XShortEnumField("type", 0x9000, ETHER_TYPES)
ShortEnumField('table_id', 1, table_id_fields ),
]
@ -421,8 +431,6 @@ class L2Controller(object):
def recv_msg_cpu(self, pkg):
packet = Ether(str(pkg))
if packet.type == 0x0800:
log.debug("Received raw (untagged) packet - BUG")
self.debug_print_pkg(pkg)
@ -432,13 +440,14 @@ class L2Controller(object):
cpu_header = CpuHeader(packet.payload)
ether_orig = Ether(src=packet.src, dst=packet.dst, type=cpu_header.type)
orig_packet = ether_orig / IP(cpu_header.load)
log.debug("cpu = {}".format(cpu_header.__repr__()))
log.debug("v4 reassambled={}".format(orig_packet.__repr__()))
elif packet.type == 0x4242:
cpu_header = CpuHeader(packet.payload)
# Not necessary anymore - cpu decoding works
# log.debug("cpu = {}".format(cpu_header.__repr__()))
log.debug("cpu = {}".format(cpu_header.__repr__()))
ether_orig = Ether(src=packet.src, dst=packet.dst, type=cpu_header.type)
@ -454,7 +463,7 @@ class L2Controller(object):
src = orig_packet['IPv6'].src
log.debug("Router solicitation from {} -- should probably handle this?".format(src))
elif cpu_header.task == self.task['DEBUG']:
log.debug("v6 reassambled={}".format(orig_packet.__repr__()))
log.debug("[debug] v6 reassambled={}".format(orig_packet.__repr__()))
elif cpu_header.task == self.task['ICMP6_NS']:
log.info("Doing neighbor solicitation for the switch in the controller")
self.handle_icmp6_ns(orig_packet)

View file

@ -12,6 +12,14 @@ typedef bit<9> port_t;
typedef bit<16> mcast_t;
typedef bit<16> task_t;
typedef bit<8> table_t; /* to map debug messages */
const bit<8> TABLE_NAT64 = 1;
const bit<8> TABLE_ICMP6 = 2;
const bit<8> TABLE_V6_NETWORKS = 3;
const bit<8> TABLE_NAT46 = 4;
const bit<8> TABLE_V4_NETWORKS = 5;
const bit<16> TYPE_IPV4 = 0x0800;
const bit<16> TYPE_IPV6 = 0x86DD;
@ -148,6 +156,7 @@ header cpu_t {
task_t task;
bit<16> ingress_port;
bit<16> ethertype;
table_t table_id;
}
struct headers {
@ -169,6 +178,7 @@ struct metadata {
task_t switch_task;
bit<16> tcp_length;
bit<32> cast_length;
table_t table_id;
}
#endif

View file

@ -32,6 +32,11 @@ control MyIngress(inout headers hdr,
clone3(CloneType.I2E, 100, meta);
}
action controller_debug_table_id(table_t table_id) {
hdr.cpu.table_id = table_id;
controller_reply(TASK_DEBUG);
}
action controller_debug() {
controller_reply(TASK_DEBUG);
}
@ -242,7 +247,6 @@ control MyIngress(inout headers hdr,
}
size = NDP_TABLE_SIZE;
default_action = NoAction;
// default_action = controller_debug;
}
/* Handle multicast registration of NDP */
@ -257,7 +261,6 @@ control MyIngress(inout headers hdr,
}
size = NDP_TABLE_SIZE;
default_action = NoAction;
// default_action = controller_debug;
}
/********************** NDP support for OTHERS (unused ATM) ***********************************/
@ -273,7 +276,7 @@ control MyIngress(inout headers hdr,
NoAction;
}
size = NDP_TABLE_SIZE;
default_action = controller_debug;
default_action = NoAction;
}
@ -306,7 +309,7 @@ control MyIngress(inout headers hdr,
NoAction;
}
size = ROUTING_TABLE_SIZE;
default_action = controller_debug;
default_action = NoAction;
}
table v4_networks {
@ -319,19 +322,30 @@ control MyIngress(inout headers hdr,
NoAction;
}
size = ROUTING_TABLE_SIZE;
default_action = controller_debug;
default_action = NoAction;
}
/********************** APPLYING TABLES ***********************************/
apply {
if(hdr.ipv6.isValid()) {
icmp6.apply(); /* icmp6 echo, icmp6 ndp */
nat64.apply(); /* v6 -> v4 */
v6_networks.apply(); /* routing, egress */
if(!icmp6.apply().hit) { /* icmp6 echo, icmp6 ndp */
controller_debug_table_id(TABLE_ICMP6);
}
if(!nat64.apply().hit) { /* v6 -> v4 */
controller_debug_table_id(TABLE_NAT64);
}
if(!v6_networks.apply().hit) {
controller_debug_table_id(TABLE_V6_NETWORKS);
}
}
if(hdr.ipv4.isValid()) {
nat46.apply(); /* v4->v6 */
v4_networks.apply(); /* routing, egress */
if(!nat46.apply().hit) { /* v4->v6 */
controller_debug_table_id(TABLE_NAT46);
}
if(!v4_networks.apply().hit) { /* routing, egress */
controller_debug_table_id(TABLE_V4_NETWORKS)
}
}
}
}
@ -351,6 +365,7 @@ control MyEgress(inout headers hdr,
hdr.cpu.ethertype = hdr.ethernet.ethertype;
hdr.cpu.ingress_port = (bit<16>) meta.ingress_port;
hdr.ethernet.ethertype = TYPE_CPU;
}
}