BUG-4692: Migrate TCP-MD5 support in bgp package to netty's native-epoll
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / attribute / sr / BindingSidLabelParser.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bgp.linkstate.attribute.sr;
9
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.Unpooled;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.protocol.bgp.linkstate.attribute.PrefixAttributesParser;
15 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SidLabelIndexParser.Size;
16 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
17 import org.opendaylight.protocol.util.BitArray;
18 import org.opendaylight.protocol.util.Ipv4Util;
19 import org.opendaylight.protocol.util.Ipv6Util;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.Ipv6SrPrefix;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabels;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabelsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.Weight;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvs;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvsBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.Flags;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCaseBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCaseBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.BindingSubTlv;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6PrefixSidCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6PrefixSidCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 public final class BindingSidLabelParser {
62
63     private static final Logger LOG = LoggerFactory.getLogger(BindingSidLabelParser.class);
64
65     private BindingSidLabelParser() {
66         throw new UnsupportedOperationException();
67     }
68
69     /* Flags */
70     private static final int FLAGS_SIZE = 8;
71     private static final int AFI = 0;
72     private static final int MIRROR_CONTEXT = 1;
73     private static final int MIRROR_CONTEXT_OSPF = 0;
74     private static final int SPREAD_TLV = 2;
75     private static final int LEAKED = 3;
76     private static final int ATTACHED = 4;
77     private static final int LOOSE = 0;
78
79     /* SID Label Tlv types */
80     private static final int ERO_METRIC = 1162;
81     private static final int ERO_IPV4 = 1163;
82     private static final int ERO_IPV6 = 1164;
83     private static final int UNNUMBERED_ERO = 1165;
84     private static final int BACKUP_ERO_IPV4 = 1166;
85     private static final int BACKUP_ERO_IPV6 = 1167;
86     private static final int BACKUP_UNNUMBERED_ERO = 1168;
87
88     private static final int RESERVED_BINDING_SID = 2;
89     private static final int RESERVED_ERO = 3;
90
91     public static SrBindingSidLabels parseBindingSidLabel(final ByteBuf buffer, final ProtocolId protocolId) {
92         final SrBindingSidLabelsBuilder bindingSid = new SrBindingSidLabelsBuilder();
93         bindingSid.setWeight(new Weight(buffer.readUnsignedByte()));
94         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
95         bindingSid.setFlags(parseBindingSidFlags(flags, protocolId));
96         buffer.skipBytes(RESERVED_BINDING_SID);
97         bindingSid.setBindingSubTlvs(parseBindingSubTlvs(buffer, protocolId));
98         return bindingSid.build();
99     }
100
101     private static Flags parseBindingSidFlags(final BitArray flags, final ProtocolId protocol) {
102         switch (protocol) {
103         case IsisLevel1:
104         case IsisLevel2:
105             return new IsisBindingFlagsCaseBuilder().setAddressFamily(flags.get(AFI)).setMirrorContext(flags.get(MIRROR_CONTEXT))
106                 .setSpreadTlv(flags.get(SPREAD_TLV)).setLeakedFromLevel2(flags.get(LEAKED)).setAttachedFlag(flags.get(ATTACHED)).build();
107         case Ospf:
108         case OspfV3:
109             return new OspfBindingFlagsCaseBuilder().setMirroring(flags.get(MIRROR_CONTEXT_OSPF)).build();
110         default:
111             return null;
112         }
113     }
114
115     private static List<BindingSubTlvs> parseBindingSubTlvs(final ByteBuf buffer, final ProtocolId protocolId) {
116         final List<BindingSubTlvs> subTlvs = new ArrayList<BindingSubTlvs>();
117         while (buffer.isReadable()) {
118             final int type = buffer.readUnsignedShort();
119             final int length = buffer.readUnsignedShort();
120             final ByteBuf slice = buffer.readSlice(length);
121             final BindingSubTlvsBuilder builder = new BindingSubTlvsBuilder();
122             parseSubTlv(type, slice, builder, protocolId);
123             subTlvs.add(builder.build());
124         }
125         return subTlvs;
126     }
127
128     private static void parseSubTlv(final int type, final ByteBuf slice, final BindingSubTlvsBuilder builder, final ProtocolId protocolId) {
129         switch (type) {
130         case SidLabelIndexParser.SID_TYPE:
131             final SidLabelIndex sid = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(slice.readableBytes()), slice);
132             builder.setBindingSubTlv(new SidLabelCaseBuilder()
133                 .setSidLabelIndex(sid).build());
134             break;
135         case PrefixAttributesParser.PREFIX_SID:
136             final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(slice, protocolId);
137             builder.setBindingSubTlv(new PrefixSidCaseBuilder()
138                 .setAlgorithm(prefix.getAlgorithm())
139                 .setFlags(prefix.getFlags())
140                 .setSidLabelIndex(prefix.getSidLabelIndex()).build());
141             break;
142         case PrefixAttributesParser.IPV6_PREFIX_SID:
143             final Ipv6SrPrefix ipv6Prefix = Ipv6SrPrefixAttributesParser.parseSrIpv6Prefix(slice);
144             builder.setBindingSubTlv(new Ipv6PrefixSidCaseBuilder().setAlgorithm(ipv6Prefix.getAlgorithm()).build());
145             break;
146         case ERO_METRIC:
147             builder.setBindingSubTlv(new EroMetricCaseBuilder()
148                 .setEroMetric(new TeMetric(slice.readUnsignedInt())).build());
149             break;
150         case ERO_IPV4:
151             final Ipv4EroCase ipv4Ero = parseIpv4EroCase(slice);
152             builder.setBindingSubTlv(new Ipv4EroCaseBuilder()
153                 .setAddress(ipv4Ero.getAddress())
154                 .setLoose(ipv4Ero.isLoose()).build());
155             break;
156         case BACKUP_ERO_IPV4:
157             final Ipv4EroCase ipv4Backup = parseIpv4EroCase(slice);
158             builder.setBindingSubTlv(new Ipv4EroBackupCaseBuilder()
159                 .setAddress(ipv4Backup.getAddress())
160                 .setLoose(ipv4Backup.isLoose()).build());
161             break;
162         case ERO_IPV6:
163             final Ipv6EroCase ipv6ero = parseIpv6EroCase(slice);
164             builder.setBindingSubTlv(new Ipv6EroCaseBuilder()
165                 .setAddress(ipv6ero.getAddress())
166                 .setLoose(ipv6ero.isLoose()).build());
167             break;
168         case BACKUP_ERO_IPV6:
169             final Ipv6EroCase ipv6backup = parseIpv6EroCase(slice);
170             builder.setBindingSubTlv(new Ipv6EroBackupCaseBuilder()
171                 .setAddress(ipv6backup.getAddress())
172                 .setLoose(ipv6backup.isLoose()).build());
173             break;
174         case UNNUMBERED_ERO:
175             final UnnumberedInterfaceIdEroCase unnumbered = parseUnnumberedEroCase(slice);
176             builder.setBindingSubTlv(new UnnumberedInterfaceIdEroCaseBuilder()
177                 .setLoose(unnumbered.isLoose())
178                 .setRouterId(unnumbered.getRouterId())
179                 .setInterfaceId(unnumbered.getInterfaceId()).build());
180             break;
181         case BACKUP_UNNUMBERED_ERO:
182             final UnnumberedInterfaceIdEroCase unnumberedBackup = parseUnnumberedEroCase(slice);
183             builder.setBindingSubTlv(new UnnumberedInterfaceIdBackupEroCaseBuilder()
184                 .setLoose(unnumberedBackup.isLoose())
185                 .setRouterId(unnumberedBackup.getRouterId())
186                 .setInterfaceId(unnumberedBackup.getInterfaceId()).build());
187             break;
188         default:
189             LOG.info("Unknown binding sub Tlv type {}", type);
190             break;
191         }
192     }
193
194     private static Ipv4EroCase parseIpv4EroCase(final ByteBuf buffer) {
195         final Ipv4EroCaseBuilder builder = new Ipv4EroCaseBuilder();
196         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
197         builder.setLoose(flags.get(LOOSE));
198         buffer.skipBytes(RESERVED_ERO);
199         builder.setAddress(Ipv4Util.addressForByteBuf(buffer));
200         return builder.build();
201     }
202
203     private static Ipv6EroCase parseIpv6EroCase(final ByteBuf buffer) {
204         final Ipv6EroCaseBuilder builder = new Ipv6EroCaseBuilder();
205         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
206         builder.setLoose(flags.get(LOOSE));
207         buffer.skipBytes(RESERVED_ERO);
208         builder.setAddress(Ipv6Util.addressForByteBuf(buffer));
209         return builder.build();
210     }
211
212     private static UnnumberedInterfaceIdEroCase parseUnnumberedEroCase(final ByteBuf buffer) {
213         final UnnumberedInterfaceIdEroCaseBuilder builder = new UnnumberedInterfaceIdEroCaseBuilder();
214         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
215         builder.setLoose(flags.get(LOOSE));
216         buffer.skipBytes(RESERVED_ERO);
217         builder.setRouterId(buffer.readUnsignedInt());
218         builder.setInterfaceId(buffer.readUnsignedInt());
219         return builder.build();
220     }
221
222     public static void serializeBindingSidLabels(final List<SrBindingSidLabels> bindingSids, final ByteBuf aggregator, final int sidType) {
223         for (final SrBindingSidLabels bindingSid : bindingSids) {
224             final ByteBuf sidBuffer = Unpooled.buffer();
225             serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(), bindingSid.getBindingSubTlvs(), sidBuffer);
226             TlvUtil.writeTLV(sidType, sidBuffer, aggregator);
227         }
228     }
229
230     static void serializeBindingSidAttributes(final Weight weight, final Flags flags, final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
231         aggregator.writeByte(weight.getValue());
232         final BitArray bitFlags = serializeBindingSidFlags(flags);
233         bitFlags.toByteBuf(aggregator);
234         aggregator.writeZero(RESERVED_BINDING_SID);
235         serializeBindingSubTlvs(bindingSubTlvs, aggregator);
236     }
237
238     private static BitArray serializeBindingSidFlags(final Flags flags) {
239         final BitArray bitFlags = new BitArray(FLAGS_SIZE);
240         if (flags instanceof IsisBindingFlagsCase) {
241             final IsisBindingFlagsCase isisFlags = (IsisBindingFlagsCase) flags;
242             bitFlags.set(AFI, isisFlags.isAddressFamily());
243             bitFlags.set(MIRROR_CONTEXT, isisFlags.isMirrorContext());
244             bitFlags.set(SPREAD_TLV, isisFlags.isSpreadTlv());
245             bitFlags.set(LEAKED, isisFlags.isLeakedFromLevel2());
246             bitFlags.set(ATTACHED, isisFlags.isAttachedFlag());
247         } else if (flags instanceof OspfBindingFlagsCase) {
248             final OspfBindingFlagsCase ospfFlags = (OspfBindingFlagsCase) flags;
249             bitFlags.set(MIRROR_CONTEXT_OSPF, ospfFlags.isMirroring());
250         }
251         return bitFlags;
252     }
253
254     private static void serializeBindingSubTlvs(final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
255         for (final BindingSubTlvs subTlv : bindingSubTlvs) {
256             ByteBuf buffer = Unpooled.buffer();
257             final BindingSubTlv bindingSubTlv = subTlv.getBindingSubTlv();
258             if (bindingSubTlv instanceof SidLabelCase) {
259                 buffer = SidLabelIndexParser.serializeSidValue(((SidLabelCase) bindingSubTlv).getSidLabelIndex());
260                 TlvUtil.writeTLV(SidLabelIndexParser.SID_TYPE, buffer, aggregator);
261             } else if (bindingSubTlv instanceof PrefixSidCase) {
262                 final PrefixSidCase prefix = (PrefixSidCase) bindingSubTlv;
263                 SrPrefixAttributesParser.serializePrefixAttributes(prefix.getFlags(), prefix.getAlgorithm(), prefix.getSidLabelIndex(), buffer);
264                 TlvUtil.writeTLV(PrefixAttributesParser.PREFIX_SID, buffer, aggregator);
265             } else if (bindingSubTlv instanceof Ipv6PrefixSidCase) {
266                 final Ipv6PrefixSidCase prefix = (Ipv6PrefixSidCase) bindingSubTlv;
267                 Ipv6SrPrefixAttributesParser.serializePrefixAttributes(prefix.getAlgorithm(), buffer);
268                 TlvUtil.writeTLV(PrefixAttributesParser.IPV6_PREFIX_SID, buffer, aggregator);
269             } else if (bindingSubTlv instanceof EroMetricCase) {
270                 buffer.writeInt(((EroMetricCase) bindingSubTlv).getEroMetric().getValue().intValue());
271                 TlvUtil.writeTLV(ERO_METRIC, buffer, aggregator);
272             } else if (bindingSubTlv instanceof Ipv4EroBackupCase) {
273                 final Ipv4EroBackupCase ipv4Backup = (Ipv4EroBackupCase) bindingSubTlv;
274                 buffer = serializeIpv4EroCase(ipv4Backup.isLoose(), ipv4Backup.getAddress());
275                 TlvUtil.writeTLV(BACKUP_ERO_IPV4, buffer, aggregator);
276             } else if (bindingSubTlv instanceof Ipv4EroCase) {
277                 final Ipv4EroCase ipv4Ero = (Ipv4EroCase) bindingSubTlv;
278                 buffer = serializeIpv4EroCase(ipv4Ero.isLoose(), ipv4Ero.getAddress());
279                 TlvUtil.writeTLV(ERO_IPV4, buffer, aggregator);
280             } else if (bindingSubTlv instanceof Ipv6EroBackupCase) {
281                 final Ipv6EroBackupCase ipv6Backup = (Ipv6EroBackupCase) bindingSubTlv;
282                 buffer = serializeIpv6EroCase(ipv6Backup.isLoose(), ipv6Backup.getAddress());
283                 TlvUtil.writeTLV(BACKUP_ERO_IPV6, buffer, aggregator);
284             } else if (bindingSubTlv instanceof Ipv6EroCase) {
285                 final Ipv6EroCase ipv6Ero = (Ipv6EroCase) bindingSubTlv;
286                 buffer = serializeIpv6EroCase(ipv6Ero.isLoose(), ipv6Ero.getAddress());
287                 TlvUtil.writeTLV(ERO_IPV6, buffer, aggregator);
288             } else if (bindingSubTlv instanceof UnnumberedInterfaceIdEroCase) {
289                 final UnnumberedInterfaceIdEroCase unnumberedEro = (UnnumberedInterfaceIdEroCase) bindingSubTlv;
290                 buffer = serializeUnnumberedIdEro(unnumberedEro.isLoose(), unnumberedEro.getRouterId(), unnumberedEro.getInterfaceId());
291                 TlvUtil.writeTLV(UNNUMBERED_ERO, buffer, aggregator);
292             } else if (bindingSubTlv instanceof UnnumberedInterfaceIdBackupEroCase) {
293                 final UnnumberedInterfaceIdBackupEroCase unnumberedBackup = (UnnumberedInterfaceIdBackupEroCase) bindingSubTlv;
294                 buffer = serializeUnnumberedIdEro(unnumberedBackup.isLoose(), unnumberedBackup.getRouterId(), unnumberedBackup.getInterfaceId());
295                 TlvUtil.writeTLV(BACKUP_UNNUMBERED_ERO, buffer, aggregator);
296             }
297         }
298     }
299
300     private static ByteBuf serializeIpv4EroCase(final Boolean loose, final Ipv4Address address) {
301         final ByteBuf buffer = Unpooled.buffer();
302         serializeEroFlags(buffer, loose);
303         buffer.writeBytes(Ipv4Util.byteBufForAddress(address));
304         return buffer;
305     }
306
307     private static ByteBuf serializeIpv6EroCase(final Boolean loose, final Ipv6Address address) {
308         final ByteBuf buffer = Unpooled.buffer();
309         serializeEroFlags(buffer, loose);
310         buffer.writeBytes(Ipv6Util.byteBufForAddress(address));
311         return buffer;
312     }
313
314     private static ByteBuf serializeUnnumberedIdEro(final Boolean loose, final Long routerId, final Long interfaceId) {
315         final ByteBuf buffer = Unpooled.buffer();
316         serializeEroFlags(buffer, loose);
317         buffer.writeInt(routerId.intValue());
318         buffer.writeInt(interfaceId.intValue());
319         return buffer;
320     }
321
322     private static void serializeEroFlags(final ByteBuf buffer, final Boolean loose) {
323         final BitArray flags = new BitArray(FLAGS_SIZE);
324         flags.set(LOOSE, loose);
325         flags.toByteBuf(buffer);
326         buffer.writeZero(RESERVED_ERO);
327     }
328 }