From 4d5aa8fb89d9b8407fa5a83eb45ce66e9fd9433d Mon Sep 17 00:00:00 2001 From: Alex Fan Date: Tue, 3 Jun 2014 19:14:57 -0700 Subject: [PATCH] Adding yang files for ethernet packet. Change-Id: I546340229a1cf07bd8a53c24680b07b75c26fa23 Signed-off-by: Alex Fan --- endpointtracker/model/pom.xml | 27 +- .../src/main/yang/l2-address-tracker.yang | 45 +++ packethandler/implementation/pom.xml | 18 ++ .../l2switch/decoder/EthernetDecoder.java | 100 +++++++ .../l2switch/decoder/EthernetDecoderTest.java | 78 +++++ packethandler/model/pom.xml | 17 +- .../model/src/main/yang/ethernet-packet.yang | 282 ++++++++++++++++++ parent/pom.xml | 5 +- 8 files changed, 567 insertions(+), 5 deletions(-) create mode 100644 endpointtracker/model/src/main/yang/l2-address-tracker.yang create mode 100644 packethandler/implementation/src/main/java/org/opendaylight/l2switch/decoder/EthernetDecoder.java create mode 100644 packethandler/implementation/src/test/java/org/opendaylight/l2switch/decoder/EthernetDecoderTest.java create mode 100644 packethandler/model/src/main/yang/ethernet-packet.yang diff --git a/endpointtracker/model/pom.xml b/endpointtracker/model/pom.xml index c1507e64..eab92201 100644 --- a/endpointtracker/model/pom.xml +++ b/endpointtracker/model/pom.xml @@ -11,7 +11,30 @@ endpointtracker-model bundle - + diff --git a/endpointtracker/model/src/main/yang/l2-address-tracker.yang b/endpointtracker/model/src/main/yang/l2-address-tracker.yang new file mode 100644 index 00000000..304deb00 --- /dev/null +++ b/endpointtracker/model/src/main/yang/l2-address-tracker.yang @@ -0,0 +1,45 @@ +module l2-address-tracker { + yang-version 1; + namespace "urn:opendaylight:l2-address-tracker"; + prefix l2-address-tracker; + + import ietf-yang-types { + prefix yang; + revision-date 2010-09-24; + } + import opendaylight-inventory { + prefix inv; + revision-date 2013-08-19; + } + + organization "Cisco Systems Inc"; + contact + "Alex Fan "; + description + "YANG version of the L2 Address Tracker Data Model"; + + revision 2014-04-02 { + description + "L2 Address Tracker module draft."; + } + + grouping l2-address { + leaf mac { + type yang:mac-address; + mandatory true; + description + "the mac address of the host."; + } + leaf node-connector-ref { + type inv:node-connector-ref; + } + } + + container l2-addresses { + config false; + list l2-address { + key "mac"; + uses l2-address; + } + } +} diff --git a/packethandler/implementation/pom.xml b/packethandler/implementation/pom.xml index 90695917..59c7ae3c 100644 --- a/packethandler/implementation/pom.xml +++ b/packethandler/implementation/pom.xml @@ -11,6 +11,24 @@ packethandler-impl bundle + + + org.opendaylight.controller + sal + ${adsal.version} + + + org.opendaylight.l2switch.packethandler + packethandler-model + ${project.version} + + + junit + junit + test + + + diff --git a/packethandler/implementation/src/main/java/org/opendaylight/l2switch/decoder/EthernetDecoder.java b/packethandler/implementation/src/main/java/org/opendaylight/l2switch/decoder/EthernetDecoder.java new file mode 100644 index 00000000..1df44dbf --- /dev/null +++ b/packethandler/implementation/src/main/java/org/opendaylight/l2switch/decoder/EthernetDecoder.java @@ -0,0 +1,100 @@ +package org.opendaylight.l2switch.decoder; + +import org.opendaylight.controller.sal.packet.BitBufferHelper; +import org.opendaylight.controller.sal.packet.BufferException; +import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.NetUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.types.rev140528.EthernetPacket; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.types.rev140528.EthernetPacketBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.types.rev140528.KnownEtherType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.types.rev140528.ethernet.packet.grp.Header8021qBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +/** + * Created by alefan on 5/29/14. + */ +public class EthernetDecoder { + private static final Logger _logger = LoggerFactory.getLogger(EthernetDecoder.class); + public static final Integer LENGTH_MAX = 1500; + public static final Integer ETHERTYPE_MIN = 1536; + public static final Integer ETHERTYPE_8021Q = 0x8100; + + // payload, 0,payload.length * NetUtils.NumBitsInAByte + + /** + * Decode a packet into an EthernetPacket + * @param data - data from wire to deserialize + * @param bitOffset - bit position where packet header starts in data + * @return + */ + public static EthernetPacket decode(byte[] data, int bitOffset) throws BufferException { + EthernetPacketBuilder builder = new EthernetPacketBuilder(); + + //0, 48, 96 = start pos + //48, 48, 16 = length in bits + + //ToDo: Possibly log these values + /*if (_logger.isTraceEnabled()) { + _logger.trace("{}: {}: {} (offset {} bitsize {})", + new Object[] { this.getClass().getSimpleName(), hdrField, + HexEncode.bytesToHexString(hdrFieldBytes), + startOffset, numBits }); + }*/ + + // Deserialize the destination & source fields + builder.setDestination(new MacAddress(HexEncode.bytesToHexStringFormat(BitBufferHelper.getBits(data, 0+bitOffset, 48)))); + builder.setSource(new MacAddress(HexEncode.bytesToHexStringFormat(BitBufferHelper.getBits(data, 48+bitOffset, 48)))); + + // Deserialize the optional field 802.1Q header + Integer nextField = BitBufferHelper.getInt(BitBufferHelper.getBits(data, 96 + bitOffset, 16)); + int extraHeaderBits = 0; + if (nextField.equals(ETHERTYPE_8021Q)) { + // Read 2 more bytes for priority (3bits), drop eligible (1bit), vlan-id (12bits) + byte[] vlanBytes = BitBufferHelper.getBits(data, 112+bitOffset, 16); + + Header8021qBuilder hBuilder = new Header8021qBuilder(); + // Remove the sign & right-shift to get the priority code + hBuilder.setPriorityCode((short)((vlanBytes[0] & 0xff) >> 5)); + + // Remove the sign & remove priority code bits & right-shift to get drop-eligible bit + hBuilder.setDropEligible(1 == (((vlanBytes[0] & 0xff) & 0x10) >> 4)); + + // Remove priority code & drop-eligible bits, to get the VLAN-id + vlanBytes[0] = (byte)(vlanBytes[0] & 0x0F); + hBuilder.setVlan(BitBufferHelper.getInt(vlanBytes)); + + // Set 802.1Q header + builder.setHeader8021q(Arrays.asList(hBuilder.build())); + + // Reset value of "nextField" to correspond to following 2 bytes for EtherType/Length + nextField = BitBufferHelper.getInt(BitBufferHelper.getBits(data, 128+bitOffset, 16)); + + // 802.1Q header means payload starts at a later position + extraHeaderBits = 32; + } + + // Deserialize the EtherType or Length field + if (nextField >= ETHERTYPE_MIN) { + builder.setEthertype(KnownEtherType.forValue(nextField)); + } + else if (nextField <= LENGTH_MAX) { + builder.setLength(nextField); + } + else { + _logger.debug("Undefined header, value is not valid EtherType or length. Value is " + nextField); + } + + // Deserialize the payload now + int payloadStart = 96 + 16 + extraHeaderBits + bitOffset; + int payloadSize = data.length * NetUtils.NumBitsInAByte - payloadStart; + int start = payloadStart / NetUtils.NumBitsInAByte; + int stop = start + payloadSize / NetUtils.NumBitsInAByte; + builder.setPayload(Arrays.copyOfRange(data, start, stop)); + + return builder.build(); + } +} diff --git a/packethandler/implementation/src/test/java/org/opendaylight/l2switch/decoder/EthernetDecoderTest.java b/packethandler/implementation/src/test/java/org/opendaylight/l2switch/decoder/EthernetDecoderTest.java new file mode 100644 index 00000000..bc82b219 --- /dev/null +++ b/packethandler/implementation/src/test/java/org/opendaylight/l2switch/decoder/EthernetDecoderTest.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sample.l2switch.md.topology; + +import org.junit.Test; +import org.opendaylight.l2switch.decoder.EthernetDecoder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.types.rev140528.EthernetPacket; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.types.rev140528.KnownEtherType; + +import java.util.Arrays; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; + +public class EthernetDecoderTest { + + @Test + public void testDecode_IPv4EtherType() throws Exception { + byte[] packet = { + 0x01, 0x23, 0x45, 0x67, (byte)0x89, (byte)0xab, + (byte)0xcd, (byte)0xef, 0x01, 0x23, 0x45, 0x67, + 0x08, 0x00, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 + }; + EthernetPacket e = EthernetDecoder.decode(packet, 0); + assertEquals(e.getEthertype(), KnownEtherType.Ipv4); + assertNull(e.getLength()); + assertNull(e.getHeader8021q()); + assertEquals(e.getDestination().getValue(), "01:23:45:67:89:ab"); + assertEquals(e.getSource().getValue(), "cd:ef:01:23:45:67"); + assertTrue(Arrays.equals(e.getPayload(), Arrays.copyOfRange(packet, 14, packet.length))); + } + + @Test + public void testDecode_Length() throws Exception { + byte[] packet = { + 0x01, 0x23, 0x45, 0x67, (byte)0x89, (byte)0xab, + (byte)0xcd, (byte)0xef, 0x01, 0x23, 0x45, 0x67, + 0x00, 0x0e, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 + }; + EthernetPacket e = EthernetDecoder.decode(packet, 0); + assertNull(e.getEthertype()); + assertEquals(e.getLength().intValue(), 14); + assertNull(e.getHeader8021q()); + assertEquals(e.getDestination().getValue(), "01:23:45:67:89:ab"); + assertEquals(e.getSource().getValue(), "cd:ef:01:23:45:67"); + assertTrue(Arrays.equals(e.getPayload(), Arrays.copyOfRange(packet, 14, packet.length))); + } + + @Test + public void testDecode_IPv6EtherTypeWith8021qHeader() throws Exception { + byte[] packet = { + 0x01, 0x23, 0x45, 0x67, (byte)0x89, (byte)0xab, + (byte)0xcd, (byte)0xef, 0x01, 0x23, 0x45, 0x67, + (byte)0x81, 0x00, + (byte)0xff, (byte)0xff, + (byte)0x86, (byte)0xdd, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 + }; + EthernetPacket e = EthernetDecoder.decode(packet, 0); + assertEquals(e.getEthertype(), KnownEtherType.Ipv6); + assertNull(e.getLength()); + assertEquals(e.getHeader8021q().size(), 1); + assertEquals(e.getHeader8021q().get(0).getPriorityCode().intValue(), 7); + assertTrue(e.getHeader8021q().get(0).isDropEligible()); + assertEquals(e.getHeader8021q().get(0).getVlan().intValue(), 4095); + assertEquals(e.getDestination().getValue(), "01:23:45:67:89:ab"); + assertEquals(e.getSource().getValue(), "cd:ef:01:23:45:67"); + assertTrue(Arrays.equals(e.getPayload(), Arrays.copyOfRange(packet, 18, packet.length))); + } +} diff --git a/packethandler/model/pom.xml b/packethandler/model/pom.xml index e0bb0857..b7774e8e 100644 --- a/packethandler/model/pom.xml +++ b/packethandler/model/pom.xml @@ -11,7 +11,20 @@ packethandler-model bundle - + diff --git a/packethandler/model/src/main/yang/ethernet-packet.yang b/packethandler/model/src/main/yang/ethernet-packet.yang new file mode 100644 index 00000000..23e23e1e --- /dev/null +++ b/packethandler/model/src/main/yang/ethernet-packet.yang @@ -0,0 +1,282 @@ +module ethernet-packet { + yang-version 1; + namespace "urn:opendaylight:packet:types"; + prefix ptypes; + + import ietf-yang-types { + prefix yang; + revision-date 2010-09-24; + } + import packet-processing { + prefix pprocessing; + revision-date 2013-07-09; + } + + organization "Cisco Systems Inc"; + contact "Alex Fan "; + + revision 2014-05-28 { + description + "Packet types module draft."; + } + + /* Taken from opendaylight-l2-types.yang, but it is commented out there -- will import once uncommented */ + typedef known-ether-type { + type enumeration { + enum "ipv4" { + value 2048; // 0x0800 + description "Internet Protocol version 4 (IPv4)"; + } + enum "arp" { + value 2054; // 0x0806 + description "Address Resolution Protocol (ARP)"; + } + enum "wake-on-lan" { + value 2114; // 0x0842 + description "Wake-on-LAN[3]"; + } + enum "ietf-trill" { + value 8947; // 0x22F3 + description "IETF TRILL Protocol"; + } + enum "decnet-phase-iv" { + value 24579; // 0x6003 + description "DECnet Phase IV"; + } + enum "reverse-arp" { + value 32821; // 0x8035 + description "Reverse Address Resolution Protocol"; + } + enum "apple-talk" { + value 32923; // 0x809B + description "AppleTalk (Ethertalk)"; + } + enum "apple-talk-arp" { + value 33011; // 0x80F3 + description "AppleTalk Address Resolution Protocol (AARP)"; + } + enum "vlan-tagged" { + value 33024; // 0x8100 + description "VLAN-tagged frame (IEEE 802.1Q) & Shortest Path Bridging IEEE 802.1aq[4]"; + } + enum "ipx" { + value 33079; // 0x8137 + description "IPX"; + } + enum "ipx2" { + value 33080; // 0x8138 + description "IPX"; + } + enum "qnx-qnet" { + value 33284; // 0x8204 + description "QNX Qnet"; + } + enum "ipv6" { + value 34525; // 0x86DD + description "Internet Protocol Version 6 (IPv6)"; + } + enum "ethernet-flow-control" { + value 34824; // 0x8808 + description "Ethernet flow control"; + } + enum "slow-protocols" { + value 34825; // 0x8809 + description "Slow Protocols (IEEE 802.3)"; + } + enum "cobra-net" { + value 34841; // 0x8819 + description "CobraNet"; + } + enum "mpls-unicast" { + value 34887; // 0x8847 + description "MPLS unicast"; + } + enum "mpls-multicast" { + value 34888; // 0x8848 + description "MPLS multicast"; + } + enum "PPP-over-ethernet-discovery" { + value 34915; // 0x8863 + description "PPPoE Discovery Stage"; + } + enum "PPP-over-ethernet-session" { + value 34916; // 0x8864 + description "PPPoE Session Stage"; + } + enum "jumbo" { + value 34928; // 0x8870 + description "Jumbo Frames[2]"; + } + enum "homeplug" { + value 34939; // 0x887B + description "HomePlug 1.0 MME"; + } + enum "eap-over-lan" { + value 34958; // 0x888E + description "EAP over LAN (IEEE 802.1X)"; + } + enum "profinet" { + value 34962; // 0x8892 + description "PROFINET Protocol"; + } + enum "hyper-scsi" { + value 34970; // 0x889A + description "HyperSCSI (SCSI over Ethernet)"; + } + enum "ata-over-ethernet" { + value 34978; // 0x88A2 + description "ATA over Ethernet"; + } + enum "ethercat" { + value 34980; // 0x88A4 + description "EtherCAT Protocol"; + } + enum "provider-bridging" { + value 34984; // 0x88A8 + description "Provider Bridging (IEEE 802.1ad) & Shortest Path Bridging IEEE 802.1aq[5]"; + } + enum "ethernet-powerlink" { + value 34987; // 0x88AB + description "Ethernet Powerlink[citation needed]"; + } + enum "lldp" { + value 35020; // 0x88CC + description "Link Layer Discovery Protocol (LLDP)"; + } + enum "sercos-3" { + value 35021; // 0x88CD + description "SERCOS III"; + } + enum "homeplug-av-mme" { + value 35041; // 0x88E1 + description "HomePlug AV MME[citation needed]"; + } + enum "media-redudancy-protocol" { + value 35043; // 0x88E3 + description "Media Redundancy Protocol (IEC62439-2)"; + } + enum "mac-security" { + value 35045; // 0x88E5 + description "MAC security (IEEE 802.1AE)"; + } + enum "precision-time-protocol" { + value 35063; // 0x88F7 + description "Precision Time Protocol (IEEE 1588)"; + } + enum "connectivity-fault-management" { + value 35074; // 0x8902 + description "IEEE 802.1ag Connectivity Fault Management (CFM) Protocol / ITU-T Recommendation Y.1731 (OAM)"; + } + enum "fibre-channel-over-ethernet" { + value 35078; // 0x8906 + description "Fibre Channel over Ethernet (FCoE)"; + } + enum "fibre-channel-over-ethernet-initialization" { + value 35092; // 0x8914 + description "FCoE Initialization Protocol"; + } + enum "rmda-over-converged-ethernet" { + value 35093; // 0x8915 + description "RDMA over Converged Ethernet (RoCE)"; + } + enum "high-availability-seamless-redudancy" { + value 35119; // 0x892F + description "High-availability Seamless Redundancy (HSR)"; + } + enum "ethernet-configuration-testing-protocol" { + value 36864; // 0x9000 + description "Ethernet Configuration Testing Protocol[6]"; + } + enum "q-in-q" { + value 37120; // 0x9100 + description "Q-in-Q"; + } + enum "veritas-low-latency" { + value 51966; // 0xCAFE + description "Veritas Low Latency Transport (LLT)[7] for Veritas Cluster Server"; + } + } + } + + typedef header8021q-type { + type enumeration { + enum "vlan-tagged" { + value 33024; // 0x8100 + description "VLAN-tagged frame (IEEE 802.1Q) & Shortest Path Bridging IEEE 802.1aq[4]"; + } + enum "q-in-q" { + value 37120; // 0x9100 + description "Q-in-Q"; + } + } + } + + grouping header8021q { + leaf type { + type header8021q-type; + } + + leaf priority-code { + type int16; + } + + leaf drop-eligible { + type boolean; + } + + leaf vlan { + type int32; + } + } + + grouping ethernet-packet-grp { + leaf source { + type yang:mac-address; + } + + leaf destination { + type yang:mac-address; + } + + list header8021q { + uses header8021q; + } + + leaf ethertype { + type known-ether-type; + } + + leaf length { + type int32; + } + + leaf payload { + type binary; + } + + container raw-packet { + uses pprocessing:raw-packet; + } + } + + container ethernet-packet { + uses ethernet-packet-grp; + } + + /*grouping ipv4-packet { + uses ethernet-packet; + } + + grouping ipv6-packet { + uses ethernet-packet; + } + + grouping lldp-packet { + uses ethernet-packet; + }*/ + + notification ethernet-packet-received { + uses ethernet-packet-grp; + } + +} \ No newline at end of file diff --git a/parent/pom.xml b/parent/pom.xml index 9c82bb4c..b7bef6f1 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -13,9 +13,12 @@ pom - 0.6.2-SNAPSHOT src/main/yang-gen-code http://nexus.opendaylight.org/content + 0.8.1-SNAPSHOT + 1.1-SNAPSHOT + 0.6.2-SNAPSHOT + 2010.09.24.4-SNAPSHOT -- 2.36.6