diff --git a/acceptance/br_multi_acceptance/conf/topology.json b/acceptance/br_multi_acceptance/conf/topology.json index bf01d4f037..c30daf4635 100644 --- a/acceptance/br_multi_acceptance/conf/topology.json +++ b/acceptance/br_multi_acceptance/conf/topology.json @@ -108,11 +108,6 @@ } } }, - "PathService": { - "psA": { "Addrs": { - "IPv4": { "Public": { "L4Port": 20005, "Addr": "192.168.0.51" } } - } } - }, "BeaconService": { "bsA": { "Addrs": { "IPv4": { "Public": { "L4Port": 20006, "Addr": "192.168.0.61" } } @@ -121,6 +116,17 @@ "CertificateService": { "csA": { "Addrs": { "IPv4": { "Public": { "L4Port": 20007, "Addr": "192.168.0.71" } } + } }, + "csB": { "Addrs": { + "IPv4": { "Public": { "L4Port": 20007, "Addr": "192.168.0.72" } } + } } + }, + "PathService": { + "psA": { "Addrs": { + "IPv4": { "Public": { "L4Port": 20005, "Addr": "192.168.0.51" } } + } }, + "psB": { "Addrs": { + "IPv4": { "Public": { "L4Port": 20055, "Addr": "192.168.0.51" } } } } } } diff --git a/acceptance/br_multi_acceptance/test b/acceptance/br_multi_acceptance/test index 5beed36072..433c1bd66f 100755 --- a/acceptance/br_multi_acceptance/test +++ b/acceptance/br_multi_acceptance/test @@ -10,7 +10,7 @@ COMMAND="${1:?}" # This function is called from test_setup set_veths() { create_veth veth_int_host veth_int 192.168.0.11/24 f0:0d:ca:fe:00:01 \ - 192.168.0.12 192.168.0.13 192.168.0.14 192.168.0.51 192.168.0.61 192.168.0.71 + 192.168.0.12 192.168.0.13 192.168.0.14 192.168.0.51 192.168.0.61 192.168.0.71 192.168.0.72 create_veth veth_121_host veth_121 192.168.12.2/31 f0:0d:ca:fe:00:12 192.168.12.3 create_veth veth_131_host veth_131 192.168.13.2/31 f0:0d:ca:fe:00:13 192.168.13.3 create_veth veth_141_host veth_141 192.168.14.2/31 f0:0d:ca:fe:00:14 192.168.14.3 diff --git a/acceptance/br_parent_acceptance/conf/topology.json b/acceptance/br_parent_acceptance/conf/topology.json index f26a33cdde..8d419c09ab 100644 --- a/acceptance/br_parent_acceptance/conf/topology.json +++ b/acceptance/br_parent_acceptance/conf/topology.json @@ -81,11 +81,6 @@ } } }, - "PathService": { - "psA": { "Addrs": { - "IPv4": { "Public": { "L4Port": 20005, "Addr": "192.168.0.51" } } - } } - }, "BeaconService": { "bsA": { "Addrs": { "IPv4": { "Public": { "L4Port": 20006, "Addr": "192.168.0.61" } } @@ -94,6 +89,17 @@ "CertificateService": { "csA": { "Addrs": { "IPv4": { "Public": { "L4Port": 20007, "Addr": "192.168.0.71" } } + } }, + "csB": { "Addrs": { + "IPv4": { "Public": { "L4Port": 20007, "Addr": "192.168.0.72" } } + } } + }, + "PathService": { + "psA": { "Addrs": { + "IPv4": { "Public": { "L4Port": 20005, "Addr": "192.168.0.51" } } + } }, + "psB": { "Addrs": { + "IPv4": { "Public": { "L4Port": 20055, "Addr": "192.168.0.51" } } } } } } diff --git a/acceptance/br_parent_acceptance/test b/acceptance/br_parent_acceptance/test index 50fa21fc51..fa5c04f1fa 100755 --- a/acceptance/br_parent_acceptance/test +++ b/acceptance/br_parent_acceptance/test @@ -10,7 +10,7 @@ COMMAND="${1:?}" # This function is called from test_setup set_veths() { create_veth veth_int_host veth_int 192.168.0.11/24 f0:0d:ca:fe:00:01 \ - 192.168.0.12 192.168.0.13 192.168.0.14 192.168.0.51 192.168.0.61 192.168.0.71 + 192.168.0.12 192.168.0.13 192.168.0.14 192.168.0.51 192.168.0.61 192.168.0.71 192.168.0.72 create_veth veth_131_host veth_131 192.168.13.2/31 f0:0d:ca:fe:00:13 192.168.13.3 } diff --git a/go/border/braccept/BUILD.bazel b/go/border/braccept/BUILD.bazel index f43861ee08..3cf494af41 100644 --- a/go/border/braccept/BUILD.bazel +++ b/go/border/braccept/BUILD.bazel @@ -21,6 +21,7 @@ go_library( "revocation_tests.go", "send.go", "sleep.go", + "svc_tests.go", ], importpath = "github.com/scionproto/scion/go/border/braccept", visibility = ["//visibility:private"], diff --git a/go/border/braccept/br_tests.go b/go/border/braccept/br_tests.go index f70010e832..729a40d298 100644 --- a/go/border/braccept/br_tests.go +++ b/go/border/braccept/br_tests.go @@ -72,5 +72,22 @@ func br_parent() int { failures += parent_to_internal_child() failures += internal_child_to_parent() + // XXX(sgmonroy) the following tests are only run for this specific BR configuration + // with a single parent interface. In the current implementation, the behavior would be + // the same regardless of the link type that the packet was recevied on. + failures += svc_anycast_parent_to_internal_host() + failures += svc_multicast_parent_to_internal_host() + failures += svc_multicast_same_host_parent_to_internal_host() + + failures += revocation_owned_parent() + failures += revocation_not_owned_child_link() + + failures += ohp_parent_to_internal_bs() + failures += ohp_udp_parent_to_internal_bs() + failures += ohp_udp_internal_bs_to_parent() + failures += ohp_internal_bs_to_parent() + + failures += parent_scmp_routing_bad_host() + return failures } diff --git a/go/border/braccept/layers/addrhdr.go b/go/border/braccept/layers/addrhdr.go index 4942160327..ca22182b59 100644 --- a/go/border/braccept/layers/addrhdr.go +++ b/go/border/braccept/layers/addrhdr.go @@ -15,7 +15,9 @@ package layers import ( + "bytes" "fmt" + "net" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/common" @@ -129,3 +131,36 @@ func (a *AddrHdr) String() string { return fmt.Sprintf("SrcIA: %s, SrcHost: %s, DstIA: %s, DstHost: %s", a.SrcIA, a.SrcHost, a.DstIA, a.DstHost) } + +var _ addr.HostAddr = (HostBad)(nil) + +type HostBad common.RawBytes + +func (h HostBad) Size() int { + return len(h) +} + +func (h HostBad) Type() addr.HostAddrType { + return addr.HostTypeNone +} + +func (h HostBad) Pack() common.RawBytes { + return common.RawBytes(h) +} + +func (h HostBad) IP() net.IP { + return nil +} + +func (h HostBad) Copy() addr.HostAddr { + return HostBad(append(common.RawBytes(nil), h...)) +} + +func (h HostBad) Equal(o addr.HostAddr) bool { + hb, ok := o.(HostBad) + return ok && bytes.Equal(h, hb) +} + +func (h HostBad) String() string { + return fmt.Sprintf("%s", common.RawBytes(h)) +} diff --git a/go/border/braccept/layers/scmp.go b/go/border/braccept/layers/scmp.go index dae5cfe339..8fdbe08742 100644 --- a/go/border/braccept/layers/scmp.go +++ b/go/border/braccept/layers/scmp.go @@ -108,6 +108,9 @@ func (s *SCMP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { func (s *SCMP) String() string { var str []string str = append(str, fmt.Sprintf("%s", &s.Hdr)) + if s.Pld == nil { + return strings.Join(str, " ") + } if s.Meta != nil { str = append(str, fmt.Sprintf("Meta={ %s }", s.Meta)) } diff --git a/go/border/braccept/layers/scnpath.go b/go/border/braccept/layers/scnpath.go index c9d00f3f62..24d18481de 100644 --- a/go/border/braccept/layers/scnpath.go +++ b/go/border/braccept/layers/scnpath.go @@ -27,6 +27,17 @@ type ScnPath struct { raw common.RawBytes } +func (p *ScnPath) Clone() *ScnPath { + clone := &ScnPath{} + clone.raw = make(common.RawBytes, len(p.raw)) + copy(clone.raw, p.raw) + clone.Segs = make([]*Segment, len(p.Segs)) + for i := range p.Segs { + clone.Segs[i] = p.Segs[i].Clone() + } + return clone +} + func (p *ScnPath) Parse(b common.RawBytes) error { if len(b) == 0 { return nil @@ -87,6 +98,18 @@ type Segment struct { Hops []*spath.HopField } +func (s *Segment) Clone() *Segment { + clone := &Segment{} + inf := *s.Inf + clone.Inf = &inf + clone.Hops = make([]*spath.HopField, len(s.Hops)) + for i := range s.Hops { + hop := *s.Hops[i] + clone.Hops[i] = &hop + } + return clone +} + func (s *Segment) Parse(b common.RawBytes) (int, error) { minSegLen := spath.InfoFieldLength + 2*spath.HopFieldLength if minSegLen > len(b) { diff --git a/go/border/braccept/parent_tests.go b/go/border/braccept/parent_tests.go index 7abd76f49d..e44a129039 100644 --- a/go/border/braccept/parent_tests.go +++ b/go/border/braccept/parent_tests.go @@ -14,6 +14,10 @@ package main +import ( + "fmt" +) + func parent_to_internal_host() int { pkt0 := AllocatePacket() pkt0.ParsePacket(` @@ -141,3 +145,181 @@ func internal_child_to_parent() int { return ExpectedPackets("internal/child to parent", defaultTimeout, pkt1) } + +func ohp_parent_to_internal_bs() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=BS + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=0 ConsEgress=0 Mac=000000 + HBH: NextHdr=HBH Type=OHP + HBH.OHP: + `) + // XXX HBH and None are the same NextHdr value + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.0.11 Dst=192.168.0.61 Checksum=0 + UDP: Src=30001 Dst=30041 + SCION: + HF_2: ConsIngress=131 ConsEgress=0 ExpTime=63 + `) + // XXX Go BR sets ExpTime to default, which is currently 63 + pkt1.SetDev("veth_int") + pkt1.SetChecksum("UDP", "IP4") + pkt1.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + SendPackets(pkt0) + + return ExpectedPackets("one-hop-path parent to internal/bs", defaultTimeout, pkt1) +} + +func ohp_udp_parent_to_internal_bs() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=BS + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=0 ConsEgress=0 Mac=000000 + HBH: NextHdr=UDP Type=OHP + HBH.OHP: + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.0.11 Dst=192.168.0.61 Checksum=0 + UDP: Src=30001 Dst=30041 + SCION: + HF_2: ConsIngress=131 ConsEgress=0 ExpTime=63 + `) + // XXX Go BR sets ExpTime to default, which is currently 63 + pkt1.SetDev("veth_int") + pkt1.SetChecksum("UDP", "IP4") + pkt1.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + SendPackets(pkt0) + + return ExpectedPackets("one-hop-path udp parent to internal/bs", defaultTimeout, pkt1) +} + +func ohp_udp_internal_bs_to_parent() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:01 EthernetType=IPv4 + IP4: Src=192.168.0.51 Dst=192.168.0.11 NextHdr=UDP Flags=DF + UDP: Src=30041 Dst=30001 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=5 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.61 DstIA=1-ff00:0:3 Dst=BS + IF_1: ISD=1 Hops=2 + HF_1: ConsIngress=131 ConsEgress=0 + HF_2: ConsIngress=0 ConsEgress=0 Mac=000000 + HBH: NextHdr=HBH Type=OHP + HBH.OHP: + `) + pkt0.SetDev("veth_int") + pkt0.SetChecksum("UDP", "IP4") + pkt0.GenerateMac("SCION", "IF_1", "HF_1", "HF_2") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:13 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.13.2 Dst=192.168.13.3 Checksum=0 + UDP: Src=50000 Dst=40000 + SCION: CurrHopF=6 + `) + pkt1.SetDev("veth_131") + pkt1.SetChecksum("UDP", "IP4") + + SendPackets(pkt0) + + return ExpectedPackets("one-hop-path up segment internal/bs to parent", defaultTimeout, pkt1) +} + +func ohp_internal_bs_to_parent() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:01 EthernetType=IPv4 + IP4: Src=192.168.0.51 Dst=192.168.0.11 NextHdr=UDP Flags=DF + UDP: Src=30041 Dst=30001 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=5 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.61 DstIA=1-ff00:0:3 Dst=BS + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=131 + HF_2: ConsIngress=0 ConsEgress=0 Mac=000000 + HBH: NextHdr=HBH Type=OHP + HBH.OHP: + `) + pkt0.SetDev("veth_int") + pkt0.SetChecksum("UDP", "IP4") + pkt0.GenerateMac("SCION", "IF_1", "HF_1", "") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:13 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.13.2 Dst=192.168.13.3 Checksum=0 + UDP: Src=50000 Dst=40000 + SCION: CurrHopF=6 + `) + pkt1.SetDev("veth_131") + pkt1.SetChecksum("UDP", "IP4") + + SendPackets(pkt0) + + return ExpectedPackets("one-hop-path internal/bs to parent", defaultTimeout, pkt1) +} + +func parent_scmp_routing_bad_host() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=0009 + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=131 ConsEgress=0 + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + pkt0.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + pkt1 := AllocatePacket() + pkt1.ParsePacket(fmt.Sprintf(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:13 DstMAC=f0:0d:ca:fe:be:ef EthernetType=IPv4 + IP4: Src=192.168.13.2 Dst=192.168.13.3 NextHdr=UDP Flags=DF Checksum=0 + UDP: Src=50000 Dst=40000 Checksum=0 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.11 DstIA=1-ff00:0:3 Dst=172.16.3.1 + IF_1: ISD=1 Hops=2 + HF_1: ConsIngress=131 ConsEgress=0 + HF_2: ConsIngress=0 ConsEgress=311 + HBH: NextHdr=SCMP Type=SCMP + HBH.SCMP: Flags=Error,HBH + SCMP: Class=ROUTING Type=BAD_HOST Checksum=0 + QUOTED: RawPkt=%s + `, pkt0.Serialize())) + pkt1.SetDev("veth_131") + pkt1.SetChecksum("UDP", "IP4") + pkt1.SetChecksum("SCMP", "SCION") + pkt1.GenerateMac("SCION", "IF_1", "HF_1", "HF_2") + + SendPackets(pkt0) + + return ExpectedPackets("parent scmp routing bad host", defaultTimeout, pkt1) +} diff --git a/go/border/braccept/parser/ctrl.go b/go/border/braccept/parser/ctrl.go index 5b1acf06e7..22a37cef4e 100644 --- a/go/border/braccept/parser/ctrl.go +++ b/go/border/braccept/parser/ctrl.go @@ -151,6 +151,9 @@ func (i *IFStateInfoTaggedLayer) Update(lines []string) { kvs := getKeyValueMap(kvStr) i.RevInfo.updateFields(kvs) i.SRevInfo = i.RevInfo.sign() + } else { + // If we are updating and the layer is not present, remove it. + i.SRevInfo = nil } infos := &path_mgmt.IFStateInfos{Infos: []*path_mgmt.IFStateInfo{&i.IFStateInfo}} pmpld, err := path_mgmt.NewPld(infos, nil) diff --git a/go/border/braccept/parser/extensions.go b/go/border/braccept/parser/extensions.go index b7442021a4..d2415089e8 100644 --- a/go/border/braccept/parser/extensions.go +++ b/go/border/braccept/parser/extensions.go @@ -130,7 +130,7 @@ type hbh_ohp struct { func (ohp *hbh_ohp) updateFields(kvs propMap) { if kvs != nil { - panic(fmt.Errorf("Unknown HBH_SCMP fields: %v", kvs)) + panic(fmt.Errorf("Unknown HBH_OHP fields: %v", kvs)) } } diff --git a/go/border/braccept/parser/helper.go b/go/border/braccept/parser/helper.go index f1a92e5dd0..5d06bd389e 100644 --- a/go/border/braccept/parser/helper.go +++ b/go/border/braccept/parser/helper.go @@ -77,7 +77,7 @@ func HexToInt(s string) uint { func HexToBytes(s string) common.RawBytes { b, err := hex.DecodeString(s) if err != nil { - panic(fmt.Sprintf("HexToBytes error converting '%s'\n", b)) + panic(fmt.Sprintf("HexToBytes error converting '%s'\n", s)) } return b } diff --git a/go/border/braccept/parser/scion.go b/go/border/braccept/parser/scion.go index 6d07c4fcb2..128f96d6c2 100644 --- a/go/border/braccept/parser/scion.go +++ b/go/border/braccept/parser/scion.go @@ -37,15 +37,13 @@ type ScionTaggedLayer struct { layers.Scion tagged options - // Tags is just a map of tag to SCION fields, use for GenerateMac or field update. - // This is slightly different than the packet layers where the order matters, hence the slice. - tags map[string]interface{} + tags scionTags } func ScionParser(lines []string) TaggedLayer { // default Scion layer values scn := &ScionTaggedLayer{} - scn.tags = make(map[string]interface{}) + scn.tags = newScionTags() //SerializeOptions scn.opts.FixLengths = true @@ -71,6 +69,20 @@ func (scn *ScionTaggedLayer) Layer() gopacket.Layer { func (scn *ScionTaggedLayer) Clone() TaggedLayer { clone := *scn + // copy scion path + path := scn.Path.Clone() + clone.Path = *path + // update cloned tags to point to the cloned info/hop fields in the path + clone.tags = newScionTags() + for i := range scn.Path.Segs { + seg := scn.Path.Segs[i] + tag := scn.tags.getTag(seg.Inf) + clone.tags.add(tag, clone.Path.Segs[i].Inf) + for j := range seg.Hops { + tag := scn.tags.getTag(seg.Hops[j]) + clone.tags.add(tag, clone.Path.Segs[i].Hops[j]) + } + } return &clone } @@ -178,16 +190,17 @@ func (scn *ScionTaggedLayer) updateAddr(kvs propMap) { var dst addr.HostAddr dst = addr.HostSVCFromString(v) if dst == addr.SvcNone { + // Try to parse IP address dst = addr.HostFromIPStr(v) if dst == nil { - panic(fmt.Errorf("invalid dst host address '%s'", v)) + dst = layers.HostBad(HexToBytes(v)) } } scn.AddrHdr.DstHost = dst case "Src": src := addr.HostFromIPStr(v) if src == nil { - panic(fmt.Errorf("invalid src host address '%s'", v)) + src = layers.HostBad(HexToBytes(v)) } scn.AddrHdr.SrcHost = src default: @@ -201,11 +214,11 @@ func (scn *ScionTaggedLayer) newIF(tag string) { inf := &spath.InfoField{TsInt: shared.TsNow32} seg.Inf = inf scn.Path.Segs = append(scn.Path.Segs, seg) - scn.addTag(tag, inf) + scn.tags.add(tag, inf) } func (scn *ScionTaggedLayer) updateIF(tag string, kvs propMap) { - inf := scn.getTag(tag).(*spath.InfoField) + inf := scn.tags.get(tag).(*spath.InfoField) if inf == nil { panic(fmt.Errorf("Invalid IF tag '%s'\n", tag)) } @@ -260,11 +273,11 @@ func (scn *ScionTaggedLayer) newHF(tag string) { hf := &spath.HopField{} hf.Mac = common.RawBytes{0xc0, 0xff, 0xee} seg.Hops = append(seg.Hops, hf) - scn.addTag(tag, hf) + scn.tags.add(tag, hf) } func (scn *ScionTaggedLayer) updateHF(tag string, kvs propMap) { - hf := scn.getTag(tag).(*spath.HopField) + hf := scn.tags.get(tag).(*spath.HopField) if hf == nil { panic(fmt.Errorf("Invalid HF tag '%s'\n", tag)) } @@ -314,12 +327,12 @@ func (scn *ScionTaggedLayer) GenerateMac(hMac hash.Hash, infTag, hfTag, hfMacTag if hMac == nil { panic(fmt.Errorf("GenerateMac: Invalid Mac %v", hMac)) } - inf := scn.getTag(infTag).(*spath.InfoField) - hf := scn.getTag(hfTag).(*spath.HopField) + inf := scn.tags.get(infTag).(*spath.InfoField) + hf := scn.tags.get(hfTag).(*spath.HopField) var hfMac *spath.HopField buf := make(common.RawBytes, spath.HopFieldLength) if hfMacTag != "" { - hfMac = scn.getTag(hfMacTag).(*spath.HopField) + hfMac = scn.tags.get(hfMacTag).(*spath.HopField) hfMac.Write(buf) } hMac.Reset() @@ -328,19 +341,43 @@ func (scn *ScionTaggedLayer) GenerateMac(hMac hash.Hash, infTag, hfTag, hfMacTag hf.Mac = hf.CalcMac(hMac, inf.TsInt, buf[1:]) } -func (scn *ScionTaggedLayer) addTag(tag string, v interface{}) { - if _, ok := scn.tags[tag]; ok { +// Tags is just a map of tag to SCION fields, used for GenerateMac or field update. +type scionTags map[string]interface{} + +func newScionTags() scionTags { + return make(map[string]interface{}) +} + +func (tags scionTags) add(tag string, v interface{}) { + if _, ok := tags[tag]; ok { panic(fmt.Errorf("Duplicated tag '%s'", tag)) } - scn.tags[tag] = v + tags[tag] = v } -func (scn *ScionTaggedLayer) getTag(tag string) interface{} { +func (tags scionTags) get(tag string) interface{} { if tag == "" { panic(fmt.Errorf("Invalid empty tag")) } - if _, ok := scn.tags[tag]; !ok { + v, ok := tags[tag] + if !ok { panic(fmt.Errorf("Tag '%s' does not exists", tag)) } - return scn.tags[tag] + return v +} + +func (tags scionTags) getTag(v interface{}) string { + matchedTags := []string{} + for tag, val := range tags { + if val == v { + matchedTags = append(matchedTags, tag) + } + } + if len(matchedTags) == 0 { + panic(fmt.Errorf("No tag for layer '%v'", v)) + } + if len(matchedTags) > 1 { + panic(fmt.Errorf("Invalid! multiple tags found for layer '%v'", v)) + } + return matchedTags[0] } diff --git a/go/border/braccept/revocation_tests.go b/go/border/braccept/revocation_tests.go index 8f74d4cffb..17ca87aaf3 100644 --- a/go/border/braccept/revocation_tests.go +++ b/go/border/braccept/revocation_tests.go @@ -275,7 +275,7 @@ func revocation_owned_peer() int { pkt0.ParsePacket(` Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:01 EthernetType=IPv4 IP4: Src=192.168.0.71 Dst=192.168.0.11 NextHdr=UDP Flags=DF - UDP: Src=30031 Dst=30001 + UDP: Src=30041 Dst=30001 SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4 ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.71 DstIA=1-ff00:0:2 Dst=172.16.2.1 IF_1: ISD=1 Hops=3 Flags=Peer,Shortcut @@ -299,7 +299,7 @@ func revocation_owned_peer() int { pkt1.ParsePacket(fmt.Sprintf(` Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef EthernetType=IPv4 IP4: Src=192.168.0.11 Dst=192.168.0.71 NextHdr=UDP Flags=DF Checksum=0 - UDP: Src=30001 Dst=30031 Checksum=0 + UDP: Src=30001 Dst=30041 Checksum=0 SCION: NextHdr=HBH CurrInfoF=8 CurrHopF=10 SrcType=IPv4 DstType=IPv4 ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.11 DstIA=1-ff00:0:1 Dst=192.168.0.71 IF_1: ISD=2 Hops=3 Flags=Peer,Shortcut @@ -351,6 +351,157 @@ func revocation_owned_peer() int { // revocation reply: // interface not owned // owned child interface -// owned parent interface -// owned peer interface // owned core interface +// overlapping revocations + +func revocation_owned_parent() int { + + shared.UpdateNow() + + ifStateDown := AllocatePacket() + ifStateDown.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:01 EthernetType=IPv4 + IP4: Src=192.168.0.61 Dst=192.168.0.11 NextHdr=UDP Flags=DF + UDP: Src=20006 Dst=30041 + SCION: NextHdr=UDP SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.61 DstIA=1-ff00:0:1 Dst=192.168.0.101 + UDP_1: Src=20006 Dst=20001 + IFStateInfo: IfID=131 Active=false + SignedRevInfo: IfID=131 IA=1-ff00:0:1 Link=parent TS=now TTL=10 + `) + ifStateDown.SetDev("veth_int") + ifStateDown.SetChecksum("UDP", "IP4") + ifStateDown.SetChecksum("UDP_1", "SCION") + + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:01 EthernetType=IPv4 + IP4: Src=192.168.0.71 Dst=192.168.0.11 NextHdr=UDP Flags=DF + UDP: Src=30041 Dst=30001 + SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=5 SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.71 DstIA=1-ff00:0:3 Dst=172.16.3.1 + IF_1: ISD=1 Hops=2 + HF_1: ConsIngress=131 ConsEgress=0 + HF_2: ConsIngress=0 ConsEgress=311 + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_int") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + pkt0.GenerateMac("SCION", "IF_1", "HF_1", "HF_2") + + // SCMP revocation reply (reversed SCION header) from the BR to the source of the packet. + pkt1 := AllocatePacket() + pkt1.ParsePacket(fmt.Sprintf(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef EthernetType=IPv4 + IP4: Src=192.168.0.11 Dst=192.168.0.71 NextHdr=UDP Flags=DF Checksum=0 + UDP: Src=30001 Dst=30041 Checksum=0 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.11 DstIA=1-ff00:0:1 Dst=192.168.0.71 + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=131 ConsEgress=0 + HBH: NextHdr=SCMP Type=SCMP + HBH.SCMP: Flags=Error,HBH + SCMP: Class=PATH Type=REVOKED_IF Checksum=0 + InfoRevocation: InfoF=4 HopF=5 IfID=131 Ingress=false + SignedRevInfo: IfID=131 IA=1-ff00:0:1 Link=parent TS=now TTL=10 + QUOTED: RawPkt=%s + `, pkt0.Serialize())) + pkt1.SetDev("veth_int") + pkt1.SetChecksum("SCMP", "SCION") + pkt1.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + // Send/Expect packets + SendPackets(ifStateDown) + Sleep("250ms") + + SendPackets(pkt0) + + ret := ExpectedPackets("revoked parent interface", defaultTimeout, pkt1) + + ifStateUp := ifStateDown.CloneAndUpdate(` + IFStateInfo: Active=true + `) + SendPackets(ifStateUp) + Sleep("250ms") + + return ret +} + +func revocation_not_owned_child_link() int { + + shared.UpdateNow() + + ifStateDown := AllocatePacket() + ifStateDown.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:01 EthernetType=IPv4 + IP4: Src=192.168.0.61 Dst=192.168.0.11 NextHdr=UDP Flags=DF + UDP: Src=20006 Dst=30041 + SCION: NextHdr=UDP SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.61 DstIA=1-ff00:0:1 Dst=192.168.0.101 + UDP_1: Src=20006 Dst=20001 + IFStateInfo: IfID=181 Active=false + SignedRevInfo: IfID=181 IA=1-ff00:0:1 Link=child TS=now TTL=10 + `) + ifStateDown.SetDev("veth_int") + ifStateDown.SetChecksum("UDP", "IP4") + ifStateDown.SetChecksum("UDP_1", "SCION") + + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:8 Dst=172.16.8.1 + IF_1: ISD=1 Hops=3 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=131 ConsEgress=181 + HF_3: ConsIngress=811 ConsEgress=0 + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + pkt0.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + // SCMP revocation reply (reversed SCION header) from the BR to the source of the packet. + pkt1 := AllocatePacket() + pkt1.ParsePacket(fmt.Sprintf(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:13 DstMAC=f0:0d:ca:fe:be:ef EthernetType=IPv4 + IP4: Src=192.168.13.2 Dst=192.168.13.3 NextHdr=UDP Flags=DF Checksum=0 + UDP: Src=50000 Dst=40000 Checksum=0 + SCION: NextHdr=HBH CurrInfoF=4 CurrHopF=7 SrcType=IPv4 DstType=IPv4 + ADDR: SrcIA=1-ff00:0:1 Src=192.168.0.11 DstIA=1-ff00:0:3 Dst=172.16.3.1 + IF_1: ISD=1 Hops=3 + HF_1: ConsIngress=811 ConsEgress=0 + HF_2: ConsIngress=131 ConsEgress=181 + HF_3: ConsIngress=0 ConsEgress=311 + HBH: NextHdr=SCMP Type=SCMP + HBH.SCMP: Flags=Error,HBH + SCMP: Class=PATH Type=REVOKED_IF Checksum=0 + InfoRevocation: InfoF=4 HopF=6 IfID=181 Ingress=true + SignedRevInfo: IfID=181 IA=1-ff00:0:1 Link=child TS=now TTL=10 + QUOTED: RawPkt=%s + `, pkt0.Serialize())) + pkt1.SetDev("veth_131") + pkt1.SetChecksum("SCMP", "SCION") + pkt1.GenerateMac("SCION", "IF_1", "HF_2", "HF_3") + + // Send/Expect packets + SendPackets(ifStateDown) + Sleep("250ms") + + SendPackets(pkt0) + + ret := ExpectedPackets("revoked child (not owned) interface", "500ms", pkt1) + + ifStateUp := ifStateDown.CloneAndUpdate(` + IFStateInfo: Active=true + `) + SendPackets(ifStateUp) + Sleep("250ms") + + return ret +} diff --git a/go/border/braccept/svc_tests.go b/go/border/braccept/svc_tests.go new file mode 100644 index 0000000000..6f87a516eb --- /dev/null +++ b/go/border/braccept/svc_tests.go @@ -0,0 +1,115 @@ +// Copyright 2019 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +func svc_anycast_parent_to_internal_host() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=BS + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=131 ConsEgress=0 + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + pkt0.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.0.11 Dst=192.168.0.61 Checksum=0 + UDP: Src=30001 Dst=30041 + `) + pkt1.SetDev("veth_int") + pkt1.SetChecksum("UDP", "IP4") + + SendPackets(pkt0) + + return ExpectedPackets("SVC anycast parent to internal/host", defaultTimeout, pkt1) +} + +func svc_multicast_parent_to_internal_host() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=CS_M + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=131 ConsEgress=0 + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + pkt0.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.0.11 Dst=192.168.0.71 Checksum=0 + UDP: Src=30001 Dst=30041 + `) + pkt1.SetDev("veth_int") + pkt1.SetChecksum("UDP", "IP4") + + pkt2 := pkt1.CloneAndUpdate(` + IP4: Src=192.168.0.11 Dst=192.168.0.72 Checksum=0 + `) + pkt2.SetDev("veth_int") + pkt2.SetChecksum("UDP", "IP4") + + SendPackets(pkt0) + + return ExpectedPackets("SVC multicast parent to internal/host", defaultTimeout, pkt1, pkt2) +} + +func svc_multicast_same_host_parent_to_internal_host() int { + pkt0 := AllocatePacket() + pkt0.ParsePacket(` + Ethernet: SrcMAC=f0:0d:ca:fe:be:ef DstMAC=f0:0d:ca:fe:00:13 EthernetType=IPv4 + IP4: Src=192.168.13.3 Dst=192.168.13.2 NextHdr=UDP Flags=DF + UDP: Src=40000 Dst=50000 + SCION: NextHdr=UDP CurrInfoF=4 CurrHopF=6 SrcType=IPv4 DstType=SVC + ADDR: SrcIA=1-ff00:0:3 Src=172.16.3.1 DstIA=1-ff00:0:1 Dst=PS_M + IF_1: ISD=1 Hops=2 Flags=ConsDir + HF_1: ConsIngress=0 ConsEgress=311 + HF_2: ConsIngress=131 ConsEgress=0 + UDP_1: Src=40111 Dst=40222 + `) + pkt0.SetDev("veth_131") + pkt0.SetChecksum("UDP", "IP4") + pkt0.SetChecksum("UDP_1", "SCION") + pkt0.GenerateMac("SCION", "IF_1", "HF_2", "HF_1") + + pkt1 := pkt0.CloneAndUpdate(` + Ethernet: SrcMAC=f0:0d:ca:fe:00:01 DstMAC=f0:0d:ca:fe:be:ef + IP4: Src=192.168.0.11 Dst=192.168.0.51 Checksum=0 + UDP: Src=30001 Dst=30041 + `) + pkt1.SetDev("veth_int") + pkt1.SetChecksum("UDP", "IP4") + + SendPackets(pkt0) + + return ExpectedPackets("SVC multicast (same host) parent to internal/host", + defaultTimeout, pkt1) +}