Extract multicast IP to Ethernet address mapping

Test: header.TestEthernetAddressFromMulticastIPAddress
PiperOrigin-RevId: 292604649
This commit is contained in:
Ghanan Gowripalan
2020-01-31 13:25:48 -08:00
committed by gVisor bot
parent bc3a24d627
commit 528dd1ec72
4 changed files with 79 additions and 35 deletions
+41
View File
@@ -134,3 +134,44 @@ func IsValidUnicastEthernetAddress(addr tcpip.LinkAddress) bool {
// addr is a valid unicast ethernet address.
return true
}
// EthernetAddressFromMulticastIPv4Address returns a multicast Ethernet address
// for a multicast IPv4 address.
//
// addr MUST be a multicast IPv4 address.
func EthernetAddressFromMulticastIPv4Address(addr tcpip.Address) tcpip.LinkAddress {
var linkAddrBytes [EthernetAddressSize]byte
// RFC 1112 Host Extensions for IP Multicasting
//
// 6.4. Extensions to an Ethernet Local Network Module:
//
// An IP host group address is mapped to an Ethernet multicast
// address by placing the low-order 23-bits of the IP address
// into the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).
linkAddrBytes[0] = 0x1
linkAddrBytes[2] = 0x5e
linkAddrBytes[3] = addr[1] & 0x7F
copy(linkAddrBytes[4:], addr[IPv4AddressSize-2:])
return tcpip.LinkAddress(linkAddrBytes[:])
}
// EthernetAddressFromMulticastIPv6Address returns a multicast Ethernet address
// for a multicast IPv6 address.
//
// addr MUST be a multicast IPv6 address.
func EthernetAddressFromMulticastIPv6Address(addr tcpip.Address) tcpip.LinkAddress {
// RFC 2464 Transmission of IPv6 Packets over Ethernet Networks
//
// 7. Address Mapping -- Multicast
//
// An IPv6 packet with a multicast destination address DST,
// consisting of the sixteen octets DST[1] through DST[16], is
// transmitted to the Ethernet multicast address whose first
// two octets are the value 3333 hexadecimal and whose last
// four octets are the last four octets of DST.
linkAddrBytes := []byte(addr[IPv6AddressSize-EthernetAddressSize:])
linkAddrBytes[0] = 0x33
linkAddrBytes[1] = 0x33
return tcpip.LinkAddress(linkAddrBytes[:])
}
+34
View File
@@ -66,3 +66,37 @@ func TestIsValidUnicastEthernetAddress(t *testing.T) {
})
}
}
func TestEthernetAddressFromMulticastIPv4Address(t *testing.T) {
tests := []struct {
name string
addr tcpip.Address
expectedLinkAddr tcpip.LinkAddress
}{
{
name: "IPv4 Multicast without 24th bit set",
addr: "\xe0\x7e\xdc\xba",
expectedLinkAddr: "\x01\x00\x5e\x7e\xdc\xba",
},
{
name: "IPv4 Multicast with 24th bit set",
addr: "\xe0\xfe\xdc\xba",
expectedLinkAddr: "\x01\x00\x5e\x7e\xdc\xba",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if got := EthernetAddressFromMulticastIPv4Address(test.addr); got != test.expectedLinkAddr {
t.Fatalf("got EthernetAddressFromMulticastIPv4Address(%s) = %s, want = %s", got, test.expectedLinkAddr)
}
})
}
}
func TestEthernetAddressFromMulticastIPv6Address(t *testing.T) {
addr := tcpip.Address("\xff\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x1a")
if got, want := EthernetAddressFromMulticastIPv6Address(addr), tcpip.LinkAddress("\x33\x33\x0d\x0e\x0f\x1a"); got != want {
t.Fatalf("got EthernetAddressFromMulticastIPv6Address(%s) = %s, want = %s", addr, got, want)
}
}
+2 -17
View File
@@ -178,24 +178,9 @@ func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bo
return broadcastMAC, true
}
if header.IsV4MulticastAddress(addr) {
// RFC 1112 Host Extensions for IP Multicasting
//
// 6.4. Extensions to an Ethernet Local Network Module:
//
// An IP host group address is mapped to an Ethernet multicast
// address by placing the low-order 23-bits of the IP address
// into the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).
return tcpip.LinkAddress([]byte{
0x01,
0x00,
0x5e,
addr[header.IPv4AddressSize-3] & 0x7f,
addr[header.IPv4AddressSize-2],
addr[header.IPv4AddressSize-1],
}), true
return header.EthernetAddressFromMulticastIPv4Address(addr), true
}
return "", false
return tcpip.LinkAddress([]byte(nil)), false
}
// SetOption implements NetworkProtocol.
+2 -18
View File
@@ -441,23 +441,7 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.
// ResolveStaticAddress implements stack.LinkAddressResolver.
func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
if header.IsV6MulticastAddress(addr) {
// RFC 2464 Transmission of IPv6 Packets over Ethernet Networks
//
// 7. Address Mapping -- Multicast
//
// An IPv6 packet with a multicast destination address DST,
// consisting of the sixteen octets DST[1] through DST[16], is
// transmitted to the Ethernet multicast address whose first
// two octets are the value 3333 hexadecimal and whose last
// four octets are the last four octets of DST.
return tcpip.LinkAddress([]byte{
0x33,
0x33,
addr[header.IPv6AddressSize-4],
addr[header.IPv6AddressSize-3],
addr[header.IPv6AddressSize-2],
addr[header.IPv6AddressSize-1],
}), true
return header.EthernetAddressFromMulticastIPv6Address(addr), true
}
return "", false
return tcpip.LinkAddress([]byte(nil)), false
}