try 42: ndp in the switch. this episode is with checksums...

This commit is contained in:
Nico Schottelius 2019-03-19 23:49:49 +01:00
parent 492888fd2f
commit c89441001b
3 changed files with 53 additions and 35 deletions

View file

@ -754,6 +754,7 @@ DEBUG:main:cpu = <CpuHeader task=ICMP6_GENERAL ingress_port=1 type=0x86dd |<Raw
DEBUG:main:reassambled=<Ether dst=00:00:0a: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=2001:db8::42 |<ICMPv6ND_NS type=Neighbor Solicitation code=0 cksum=0x82b res=0 tgt=2001:db8::42 |<ICMPv6NDOptSrcLLAddr type=1 len=1 lladdr=00:00:0a:00:00:01 |>>>> DEBUG:main:reassambled=<Ether dst=00:00:0a: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=2001:db8::42 |<ICMPv6ND_NS type=Neighbor Solicitation code=0 cksum=0x82b res=0 tgt=2001:db8::42 |<ICMPv6NDOptSrcLLAddr type=1 len=1 lladdr=00:00:0a:00:00:01 |>>>>
***** TODO Debug why neighbor discover does not work anymore ***** TODO Debug why neighbor discover does not work anymore
****** log
p4@ubuntu:~$ mx h1 tcpdump -lni any p4@ubuntu:~$ mx h1 tcpdump -lni any
sudo: unable to resolve host ubuntu sudo: unable to resolve host ubuntu
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
@ -767,10 +768,28 @@ DEBUG:main:cpu = <CpuHeader task=ICMP6_NS ingress_port=1 type=0x86dd |<Raw loa
DEBUG:main: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: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 |>>>>
INFO:main:Doing neighbor solicitation INFO:main:Doing neighbor solicitation
DEBUG:main:OUTGOING: <Ether dst=00:00:0a:00:00:01 src=00:00:0a:00:00:42 type=0x86dd |<IPv6 nh=ICMPv6 hlim=255 src=2001:db8::42 dst=fe80::200:aff:fe00:1 |<ICMPv6ND_NA cksum=None R=0 S=1 tgt=2001:db8::42 |<ICMPv6NDOptDstLLAddr lladdr=00:00:0a:00:00:42 |>>>> DEBUG:main:OUTGOING: <Ether dst=00:00:0a:00:00:01 src=00:00:0a:00:00:42 type=0x86dd |<IPv6 nh=ICMPv6 hlim=255 src=2001:db8::42 dst=fe80::200:aff:fe00:1 |<ICMPv6ND_NA cksum=None R=0 S=1 tgt=2001:db8::42 |<ICMPv6NDOptDstLLAddr lladdr=00:00:0a:00:00:42 |>>>>
DEBUG:main:INCOMING: <Ether dst=00:00:0a:00:00:01 src=00:00:0a:00:00:42 type=0x86dd |<IPv6 version=6 tc=0 fl=0 plen=32 nh=ICMPv6 hlim=255 src=2001:db8::42 dst=fe80::200:aff:fe00:1 |<ICMPv6ND_NA type=Neighbor Advertisement code=0 cksum=0xa5e9 R=0 S=1 O=1 res=0x0 tgt=2001:db8::42 |<ICMPv6NDOptDstLLAddr type=2 len=1 lladdr=00:00:0a:00:00:42 |>>>> DEBUG:main:INCOMING: <Ether dst=00:00:0a:00:00:01
****** Do we have a routing for fe80::/10? Probably not. Shouldn't we see it in the controller then? src=00:00:0a:00:00:42 type=0x86dd |<IPv6 version=6 tc=0 fl=0 plen=32
****** TODO Implement address learning? nh=ICMPv6 hlim=255 src=2001:db8::42
****** TODO Not sure whether we should react on router solicitation dst=fe80::200:aff:fe00:1 |<ICMPv6ND_NA type=Neighbor Advertisement
code=0 cksum=0xa5e9 R=0 S=1 O=1 res=0x0
tgt=2001:db8::42 |<ICMPv6NDOptDstLLAddr type=2 len=1
lladdr=00:00:0a:00:00:42 |>>>>
After removing noise:
DEBUG:main: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: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: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: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: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 |>>>>
****** Do we have routing for fe80::/10? Probably not. Shouldn't we see it in the controller then?
****** NDP is controller only!
***** TODO Maybe merge v6_address and v6_networks - /128 is the same
***** TODO Implement address learning?
***** TODO Not sure whether we should react on router solicitation
- Using static routes -> should do the job - Using static routes -> should do the job
***** TODO Implement the calculation ***** TODO Implement the calculation
***** TODO Sketch the flow for session handling for icmp6 w/o packet loss ***** TODO Sketch the flow for session handling for icmp6 w/o packet loss

View file

@ -47,6 +47,8 @@ class L2Controller(object):
self.task = dict(reversed(item) for item in cpu_fields.items()) self.task = dict(reversed(item) for item in cpu_fields.items())
self.info={} self.info={}
# https://en.wikipedia.org/wiki/Solicited-node_multicast_address
self.info['ndp_multicast'] = ipaddress.ip_network("ff02::1:ff00:0/104") self.info['ndp_multicast'] = ipaddress.ip_network("ff02::1:ff00:0/104")
self.info['mac_address'] = "00:00:0a:00:00:42" self.info['mac_address'] = "00:00:0a:00:00:42"
self.info['ipv6_link_local'] = ipaddress.ip_address("fe80::200:aff:fe00:42") self.info['ipv6_link_local'] = ipaddress.ip_address("fe80::200:aff:fe00:42")
@ -136,7 +138,6 @@ class L2Controller(object):
return addr return addr
def init_other_port_multicast_groups(self): def init_other_port_multicast_groups(self):
""" map multicast group x to send to """ map multicast group x to send to
all ports but x - basically broadcasting without sending back to ourselves all ports but x - basically broadcasting without sending back to ourselves
@ -153,21 +154,6 @@ class L2Controller(object):
self.controller.mc_node_associate(g_handle, n_handle) self.controller.mc_node_associate(g_handle, n_handle)
def init_ndp(self):
""" initialise neighbor discovery protocol"""
# https://en.wikipedia.org/wiki/Solicited-node_multicast_address
ndp_prefix = "ff02::1:ff00:0/104"
self.controller.table_clear("ndp")
for port in self.ports:
self.controller.table_add("ndp", "multicast_pkg", [ndp_prefix, str(port)], [str(port)])
# Special rule for switch entries
self.controller.table_add("ndp_answer", "icmp6_neighbor_solicitation", ["ff02::1:ff00:42", "135"], ["2001:db8:61::42"])
def init_boilerplate(self, sw_name): def init_boilerplate(self, sw_name):
self.topo = Topology(db="topology.db") self.topo = Topology(db="topology.db")
self.sw_name = sw_name self.sw_name = sw_name
@ -180,8 +166,6 @@ class L2Controller(object):
if self.cpu_port: if self.cpu_port:
self.controller.mirroring_add(100, self.cpu_port) self.controller.mirroring_add(100, self.cpu_port)
# self.init_ndp()
def config(self): def config(self):
self.fill_tables() self.fill_tables()
self.config_hosts() self.config_hosts()
@ -192,6 +176,14 @@ class L2Controller(object):
net = self.info['ndp_multicast'] net = self.info['ndp_multicast']
self.controller.table_add("v6_networks", "controller_debug", [str(net)]) self.controller.table_add("v6_networks", "controller_debug", [str(net)])
def init_ndp_in_switch(self, addr):
icmp6_addr = self.gen_ndp_multicast_addr(addr)
icmp6_net = "{}/128".format(icmp6_addr)
self.controller.table_add("v6_networks",
"icmp6_neighbor_solicitation",
[str(icmp6_net)], [str(addr)])
def fill_tables(self): def fill_tables(self):
self.controller.table_clear("v6_networks") self.controller.table_clear("v6_networks")
for v6route in self.v6_routes[self.mode]: for v6route in self.v6_routes[self.mode]:
@ -200,6 +192,9 @@ class L2Controller(object):
if self.args.multicast_to_controller: if self.args.multicast_to_controller:
self.listen_to_icmp6_multicast() self.listen_to_icmp6_multicast()
for v6addr in self.v6_addresses[self.mode]:
self.init_ndp_in_switch(v6addr)
self.controller.table_clear("v4_networks") self.controller.table_clear("v4_networks")
for v4route in self.v4_routes[self.mode]: for v4route in self.v4_routes[self.mode]:
self.controller.table_add("v4_networks", "set_egress_port", [str(v4route['net'])], [str(v4route['port'])]) self.controller.table_add("v4_networks", "set_egress_port", [str(v4route['net'])], [str(v4route['port'])])
@ -401,7 +396,7 @@ class L2Controller(object):
log.debug("Neighbor solicitation for checking her own IP address") log.debug("Neighbor solicitation for checking her own IP address")
elif ICMPv6MLReport2 in orig_packet and orig_packet['IPv6'].dst == 'ff02::16': elif ICMPv6MLReport2 in orig_packet and orig_packet['IPv6'].dst == 'ff02::16':
mc_group = orig_packet['ICMPv6MLDMultAddrRec'].dst mc_group = orig_packet['ICMPv6MLDMultAddrRec'].dst
log.debug("Multicast registration for {} from {} -- should probably handle this".format(mc_group, cpu_header.ingress_port)) log.debug("Multicast registration for {} port {} -- should probably handle this".format(mc_group, cpu_header.ingress_port))
elif ICMPv6ND_RS in orig_packet and orig_packet['IPv6'].dst == 'ff02::2': elif ICMPv6ND_RS in orig_packet and orig_packet['IPv6'].dst == 'ff02::2':
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))

View file

@ -49,6 +49,10 @@ control MyIngress(inout headers hdr,
hdr.ipv6.dst_addr = hdr.ipv6.src_addr; hdr.ipv6.dst_addr = hdr.ipv6.src_addr;
hdr.ipv6.src_addr = addr; hdr.ipv6.src_addr = addr;
hdr.icmp6.type = ICMP6_NA; hdr.icmp6.type = ICMP6_NA;
/* checksum trigger / content */
meta.do_cksum = 1;
meta.cast_length = (bit<32>) hdr.ipv6.payload_length;
} }
action icmp6_echo_reply() { action icmp6_echo_reply() {