blob: 07ead0c764b7b2275183f5082bc653d4607e0f2b [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska58de4162015-09-10 16:15:33 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
sanghob35a6192015-04-01 13:05:26 -070016package org.onlab.packet;
17
18import java.nio.ByteBuffer;
sanghob35a6192015-04-01 13:05:26 -070019import java.util.Map;
20
Yuta HIGUCHIbfc2e922017-06-07 21:46:05 -070021import com.google.common.collect.ImmutableMap;
22
Jian Li5fc14292015-12-04 11:30:46 -080023import static com.google.common.base.MoreObjects.toStringHelper;
Jonathan Hart2a655752015-04-07 16:46:33 -070024import static org.onlab.packet.PacketUtils.checkInput;
25
Jian Li5fc14292015-12-04 11:30:46 -080026/**
27 * Representation of an MPLS Packet.
28 */
sanghob35a6192015-04-01 13:05:26 -070029public class MPLS extends BasePacket {
Jonathan Hart2a655752015-04-07 16:46:33 -070030 public static final int HEADER_LENGTH = 4;
31
sanghob35a6192015-04-01 13:05:26 -070032 public static final byte PROTOCOL_IPV4 = 0x1;
pierf8e328d2019-06-28 22:17:31 +020033 public static final byte PROTOCOL_IPV6 = 0x2;
sanghob35a6192015-04-01 13:05:26 -070034 public static final byte PROTOCOL_MPLS = 0x6;
Yuta HIGUCHIbfc2e922017-06-07 21:46:05 -070035 // mutable for Testing
36 static Map<Byte, Deserializer<? extends IPacket>> protocolDeserializerMap =
37 ImmutableMap.<Byte, Deserializer<? extends IPacket>>builder()
pierf8e328d2019-06-28 22:17:31 +020038 .put(PROTOCOL_IPV6, IPv6.deserializer())
39 .put(PROTOCOL_IPV4, IPv4.deserializer())
40 .put(PROTOCOL_MPLS, MPLS.deserializer())
41 .build();
sanghob35a6192015-04-01 13:05:26 -070042
43 protected int label; //20bits
44 protected byte bos; //1bit
45 protected byte ttl; //8bits
46 protected byte protocol;
47
48 /**
49 * Default constructor that sets the version to 4.
50 */
51 public MPLS() {
52 super();
53 this.bos = 1;
54 this.protocol = PROTOCOL_IPV4;
55 }
56
57 @Override
58 public byte[] serialize() {
59 byte[] payloadData = null;
60 if (payload != null) {
61 payload.setParent(this);
62 payloadData = payload.serialize();
63 }
64
65 byte[] data = new byte[(4 + ((payloadData != null) ? payloadData.length : 0)) ];
66 ByteBuffer bb = ByteBuffer.wrap(data);
67
68 bb.putInt(((this.label & 0x000fffff) << 12) | ((this.bos & 0x1) << 8 | (this.ttl & 0xff)));
69 if (payloadData != null) {
70 bb.put(payloadData);
71 }
72
73 return data;
74 }
75
sanghob35a6192015-04-01 13:05:26 -070076
77 /**
78 * Returns the MPLS label.
79 *
80 * @return MPLS label
81 */
82 public int getLabel() {
83 return label;
84 }
85
86 /**
87 * Sets the MPLS label.
88 *
Thomas Vachuskae10f56b2015-04-15 18:20:08 -070089 * @param label MPLS label
sanghob35a6192015-04-01 13:05:26 -070090 */
91 public void setLabel(int label) {
92 this.label = label;
93 }
94
95 /**
96 * Returns the MPLS TTL of the packet.
97 *
98 * @return MPLS TTL of the packet
99 */
100 public byte getTtl() {
101 return ttl;
102 }
103
104 /**
105 * Sets the MPLS TTL of the packet.
106 *
107 * @param ttl MPLS TTL
108 */
109 public void setTtl(byte ttl) {
110 this.ttl = ttl;
111 }
112
pierf8e328d2019-06-28 22:17:31 +0200113 @Override
114 public IPacket setPayload(final IPacket payload) {
115 // We implicitly assume that traffic can be only of these three types
116 if (payload instanceof MPLS) {
117 this.bos = 0;
118 this.protocol = PROTOCOL_MPLS;
119 } else if (payload instanceof IPv6) {
120 this.bos = 1;
121 this.protocol = PROTOCOL_IPV6;
122 } else {
123 this.bos = 1;
124 this.protocol = PROTOCOL_IPV4;
125 }
126 return super.setPayload(payload);
127 }
128
Jonathan Hart2a655752015-04-07 16:46:33 -0700129 /**
130 * Deserializer function for MPLS packets.
131 *
132 * @return deserializer function
133 */
134 public static Deserializer<MPLS> deserializer() {
135 return (data, offset, length) -> {
136 checkInput(data, offset, length, HEADER_LENGTH);
137
138 MPLS mpls = new MPLS();
139 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
140
141 int mplsheader = bb.getInt();
142 mpls.label = ((mplsheader & 0xfffff000) >>> 12);
143 mpls.bos = (byte) ((mplsheader & 0x00000100) >> 8);
144 mpls.ttl = (byte) (mplsheader & 0x000000ff);
pierf8e328d2019-06-28 22:17:31 +0200145
146 ByteBuffer duplicate = bb.duplicate();
147 short protocol = (short) ((duplicate.get() & 0xf0) >> 4);
148 mpls.protocol = (mpls.bos == 1) ? protocol == 4 ?
149 PROTOCOL_IPV4 : PROTOCOL_IPV6 : PROTOCOL_MPLS;
Jonathan Hart2a655752015-04-07 16:46:33 -0700150
151 Deserializer<? extends IPacket> deserializer;
152 if (protocolDeserializerMap.containsKey(mpls.protocol)) {
153 deserializer = protocolDeserializerMap.get(mpls.protocol);
154 } else {
155 deserializer = Data.deserializer();
156 }
157 mpls.payload = deserializer.deserialize(data, bb.position(), bb.limit() - bb.position());
158 mpls.payload.setParent(mpls);
159
160 return mpls;
161 };
162 }
Jian Li5fc14292015-12-04 11:30:46 -0800163
164 @Override
165 public String toString() {
166 return toStringHelper(getClass())
167 .add("label", Integer.toString(label))
168 .add("bos", Byte.toString(bos))
169 .add("ttl", Byte.toString(ttl))
170 .add("protocol", Byte.toString(protocol))
171 .toString();
172 }
sanghob35a6192015-04-01 13:05:26 -0700173}