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! table -> need different task field!
***** try2: checksum ok, but no packets on h3 ***** 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 *** TODO Get p4 VM / vagrant running
**** DONE install libvirtd-daemon **** DONE install libvirtd-daemon
@ -1219,8 +1236,8 @@ debug packets - analyse code - goto 1
[21:26] line:~% sudo apt install thrift-compiler [21:26] line:~% sudo apt install thrift-compiler
libnanomsg-dev libjudy-dev libnanomsg-dev libjudy-dev
*** Performance comparison *** Performance comparison
*** Feature/Functionality difference / overview / CHALLENGES / LIMITATIONS in P4 *** Challenges / Limitations in P4
**** P4: cannot read key from table **** DONE cannot read key from table
***** log ***** log
Key and mask for matching destination is in table. We need this Key and mask for matching destination is in table. We need this
information in the action. However this information is not exposed, so information in the action. However this information is not exposed, so
@ -1285,7 +1302,7 @@ Need to duplicate information
**** DONE ICMP6: checksum over payload **** DONE ICMP6: checksum over payload
- variable length, up to 65k - variable length, up to 65k
Exists! Exists!
**** Synchronisation with the controller **** DONE Synchronisation with the controller
- Double data type definition -> might differ - Double data type definition -> might differ
- TYPE_CPU for ethernet - TYPE_CPU for ethernet
- Port ingress offset (9 vs. 16 bit) - Port ingress offset (9 vs. 16 bit)
@ -1315,18 +1332,29 @@ Code:
} }
#+END_SRC #+END_SRC
**** (current) Implementation limitations **** No table meta information for default actions (asked 2019-03-25)
***** No fragmentation support (yet) Is there any meta information for "from which table was the action
***** No session handling (yet) 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. 1:1 mappings. No (automatic) session.
***** IPv4 / IPv6 embedding **** IPv4 / IPv6 embedding
Currently offset based - probably not following the RFC! Currently offset based - probably not following the RFC!
***** No DNS64 **** No DNS64
has already been solved in a different domain - could even do has already been solved in a different domain - could even do
transparent / in network modification transparent / in network modification
***** Incomplete NDP **** Incomplete NDP
Very limited option support Very limited option support
***** NAT64 mappings not source network dependent **** NAT64 mappings not source network dependent
Only the destination network is matched for deciding on NAT64, as Only the destination network is matched for deciding on NAT64, as
priority based double LPM is not supported. This limits a prefix to be priority based double LPM is not supported. This limits a prefix to be
used only in one network. used only in one network.

View File

@ -23,11 +23,20 @@ log = logging.getLogger("main")
cpu_fields = { cpu_fields = {
0: 'UNSET',
1: 'ICMP6_NS', 1: 'ICMP6_NS',
2: 'ICMP6_GENERAL', 2: 'ICMP6_GENERAL',
3: 'DEBUG' 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): class CpuHeader(Packet):
name = 'CpuPacket' name = 'CpuPacket'
@ -35,6 +44,7 @@ class CpuHeader(Packet):
ShortEnumField('task', 1, cpu_fields ), ShortEnumField('task', 1, cpu_fields ),
ShortField('ingress_port', 0), ShortField('ingress_port', 0),
XShortEnumField("type", 0x9000, ETHER_TYPES) 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): def recv_msg_cpu(self, pkg):
packet = Ether(str(pkg)) packet = Ether(str(pkg))
if packet.type == 0x0800: if packet.type == 0x0800:
log.debug("Received raw (untagged) packet - BUG") log.debug("Received raw (untagged) packet - BUG")
self.debug_print_pkg(pkg) self.debug_print_pkg(pkg)
@ -432,13 +440,14 @@ class L2Controller(object):
cpu_header = CpuHeader(packet.payload) cpu_header = CpuHeader(packet.payload)
ether_orig = Ether(src=packet.src, dst=packet.dst, type=cpu_header.type) ether_orig = Ether(src=packet.src, dst=packet.dst, type=cpu_header.type)
orig_packet = ether_orig / IP(cpu_header.load) orig_packet = ether_orig / IP(cpu_header.load)
log.debug("cpu = {}".format(cpu_header.__repr__()))
log.debug("v4 reassambled={}".format(orig_packet.__repr__())) log.debug("v4 reassambled={}".format(orig_packet.__repr__()))
elif packet.type == 0x4242: elif packet.type == 0x4242:
cpu_header = CpuHeader(packet.payload) cpu_header = CpuHeader(packet.payload)
# Not necessary anymore - cpu decoding works # 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) 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 src = orig_packet['IPv6'].src
log.debug("Router solicitation from {} -- should probably handle this?".format(src)) log.debug("Router solicitation from {} -- should probably handle this?".format(src))
elif cpu_header.task == self.task['DEBUG']: 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']: elif cpu_header.task == self.task['ICMP6_NS']:
log.info("Doing neighbor solicitation for the switch in the controller") log.info("Doing neighbor solicitation for the switch in the controller")
self.handle_icmp6_ns(orig_packet) 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> mcast_t;
typedef bit<16> task_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_IPV4 = 0x0800;
const bit<16> TYPE_IPV6 = 0x86DD; const bit<16> TYPE_IPV6 = 0x86DD;
@ -148,6 +156,7 @@ header cpu_t {
task_t task; task_t task;
bit<16> ingress_port; bit<16> ingress_port;
bit<16> ethertype; bit<16> ethertype;
table_t table_id;
} }
struct headers { struct headers {
@ -169,6 +178,7 @@ struct metadata {
task_t switch_task; task_t switch_task;
bit<16> tcp_length; bit<16> tcp_length;
bit<32> cast_length; bit<32> cast_length;
table_t table_id;
} }
#endif #endif

View File

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