blob: dc6538e76c1121e34dfecdb6146149a00ef59efd [file] [log] [blame]
Ray Milkey1f95bd32014-12-10 11:11:00 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Ray Milkey1f95bd32014-12-10 11:11:00 -08003 *
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 */
16package org.onosproject.codec.impl;
17
Seyeon Jeong2000d012020-02-28 01:46:39 -080018import com.fasterxml.jackson.databind.JsonNode;
Ray Milkey1f95bd32014-12-10 11:11:00 -080019import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
Seyeon Jeong2000d012020-02-28 01:46:39 -080021import org.onlab.packet.EthType;
22import org.onlab.packet.IpAddress;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.VlanId;
25import org.onosproject.codec.CodecContext;
26import org.onosproject.codec.JsonCodec;
27import org.onosproject.net.Annotations;
28import org.onosproject.net.DefaultHost;
29import org.onosproject.net.Host;
30import org.onosproject.net.HostId;
31import org.onosproject.net.HostLocation;
32import org.onosproject.net.provider.ProviderId;
33
34import java.util.HashSet;
35import java.util.Set;
36import java.util.stream.Collectors;
Ray Milkey1f95bd32014-12-10 11:11:00 -080037
38import static com.google.common.base.Preconditions.checkNotNull;
Seyeon Jeong2000d012020-02-28 01:46:39 -080039import static org.onlab.util.Tools.nullIsIllegal;
Ray Milkey1f95bd32014-12-10 11:11:00 -080040
41/**
Seyeon Jeong2000d012020-02-28 01:46:39 -080042 * JSON codec for Host class.
Ray Milkey1f95bd32014-12-10 11:11:00 -080043 */
Ray Milkey540b2ce2015-02-04 17:50:20 -080044public final class HostCodec extends AnnotatedCodec<Host> {
Ray Milkey1f95bd32014-12-10 11:11:00 -080045
Seyeon Jeong2000d012020-02-28 01:46:39 -080046 // JSON field names
47 public static final String HOST_ID = "id";
48 public static final String MAC = "mac";
49 public static final String VLAN = "vlan";
50 public static final String INNER_VLAN = "innerVlan";
51 public static final String OUTER_TPID = "outerTpid";
52 public static final String IS_CONFIGURED = "configured";
53 public static final String IS_SUSPENDED = "suspended";
54 public static final String IP_ADDRESSES = "ipAddresses";
55 public static final String HOST_LOCATIONS = "locations";
56 public static final String AUX_LOCATIONS = "auxLocations";
57
58 private static final String NULL_OBJECT_MSG = "Host cannot be null";
59 private static final String MISSING_MEMBER_MESSAGE = " member is required in Host";
60
Ray Milkey1f95bd32014-12-10 11:11:00 -080061 @Override
62 public ObjectNode encode(Host host, CodecContext context) {
Seyeon Jeong2000d012020-02-28 01:46:39 -080063 checkNotNull(host, NULL_OBJECT_MSG);
64
Ray Milkeyc95bb9d2015-01-06 10:28:24 -080065 final JsonCodec<HostLocation> locationCodec =
66 context.codec(HostLocation.class);
Seyeon Jeong2000d012020-02-28 01:46:39 -080067 // keep fields in string for compatibility
Ray Milkey1f95bd32014-12-10 11:11:00 -080068 final ObjectNode result = context.mapper().createObjectNode()
Seyeon Jeong2000d012020-02-28 01:46:39 -080069 .put(HOST_ID, host.id().toString())
70 .put(MAC, host.mac().toString())
71 .put(VLAN, host.vlan().toString())
72 .put(INNER_VLAN, host.innerVlan().toString())
73 // use a 4-digit hex string in coding an ethernet type
74 .put(OUTER_TPID, String.format("0x%04x", host.tpid().toShort()))
75 .put(IS_CONFIGURED, host.configured())
76 .put(IS_SUSPENDED, host.suspended());
Ray Milkey1f95bd32014-12-10 11:11:00 -080077
Seyeon Jeong2000d012020-02-28 01:46:39 -080078 final ArrayNode jsonIpAddresses = result.putArray(IP_ADDRESSES);
Ray Milkey1f95bd32014-12-10 11:11:00 -080079 for (final IpAddress ipAddress : host.ipAddresses()) {
80 jsonIpAddresses.add(ipAddress.toString());
81 }
Seyeon Jeong2000d012020-02-28 01:46:39 -080082 result.set(IP_ADDRESSES, jsonIpAddresses);
Charles Chancd06c692017-04-27 20:46:06 -070083
Seyeon Jeong2000d012020-02-28 01:46:39 -080084 final ArrayNode jsonLocations = result.putArray(HOST_LOCATIONS);
Charles Chancd06c692017-04-27 20:46:06 -070085 for (final HostLocation location : host.locations()) {
86 jsonLocations.add(locationCodec.encode(location, context));
87 }
Seyeon Jeong2000d012020-02-28 01:46:39 -080088 result.set(HOST_LOCATIONS, jsonLocations);
Ray Milkey1f95bd32014-12-10 11:11:00 -080089
Charles Chan42d109d2019-12-18 15:49:39 -080090 if (host.auxLocations() != null) {
Seyeon Jeong2000d012020-02-28 01:46:39 -080091 final ArrayNode jsonAuxLocations = result.putArray(AUX_LOCATIONS);
Charles Chan42d109d2019-12-18 15:49:39 -080092 for (final HostLocation auxLocation : host.auxLocations()) {
93 jsonAuxLocations.add(locationCodec.encode(auxLocation, context));
94 }
Seyeon Jeong2000d012020-02-28 01:46:39 -080095 result.set(AUX_LOCATIONS, jsonAuxLocations);
Charles Chan42d109d2019-12-18 15:49:39 -080096 }
97
Ray Milkey1f95bd32014-12-10 11:11:00 -080098 return annotate(result, host, context);
99 }
100
Seyeon Jeong2000d012020-02-28 01:46:39 -0800101 @Override
102 public Host decode(ObjectNode json, CodecContext context) {
103 if (json == null || !json.isObject()) {
104 return null;
105 }
Ray Milkey1f95bd32014-12-10 11:11:00 -0800106
Seyeon Jeong2000d012020-02-28 01:46:39 -0800107 MacAddress mac = MacAddress.valueOf(nullIsIllegal(
108 json.get(MAC), MAC + MISSING_MEMBER_MESSAGE).asText());
109 VlanId vlanId = VlanId.vlanId(nullIsIllegal(
110 json.get(VLAN), VLAN + MISSING_MEMBER_MESSAGE).asText());
111 HostId id = HostId.hostId(mac, vlanId);
112
113 ArrayNode locationNodes = nullIsIllegal(
114 (ArrayNode) json.get(HOST_LOCATIONS), HOST_LOCATIONS + MISSING_MEMBER_MESSAGE);
115 Set<HostLocation> hostLocations =
116 context.codec(HostLocation.class).decode(locationNodes, context)
117 .stream().collect(Collectors.toSet());
118
119 ArrayNode ipNodes = nullIsIllegal(
120 (ArrayNode) json.get(IP_ADDRESSES), IP_ADDRESSES + MISSING_MEMBER_MESSAGE);
121 Set<IpAddress> ips = new HashSet<>();
122 ipNodes.forEach(ipNode -> {
123 ips.add(IpAddress.valueOf(ipNode.asText()));
124 });
125
126 // check optional fields
127 JsonNode innerVlanIdNode = json.get(INNER_VLAN);
128 VlanId innerVlanId = (null == innerVlanIdNode) ? VlanId.NONE :
129 VlanId.vlanId(innerVlanIdNode.asText());
130 JsonNode outerTpidNode = json.get(OUTER_TPID);
131 EthType outerTpid = (null == outerTpidNode) ? EthType.EtherType.UNKNOWN.ethType() :
132 EthType.EtherType.lookup((short) (Integer.decode(outerTpidNode.asText()) & 0xFFFF)).ethType();
133 JsonNode configuredNode = json.get(IS_CONFIGURED);
134 boolean configured = (null == configuredNode) ? false : configuredNode.asBoolean();
135 JsonNode suspendedNode = json.get(IS_SUSPENDED);
136 boolean suspended = (null == suspendedNode) ? false : suspendedNode.asBoolean();
137
138 ArrayNode auxLocationNodes = (ArrayNode) json.get(AUX_LOCATIONS);
139 Set<HostLocation> auxHostLocations = (null == auxLocationNodes) ? null :
140 context.codec(HostLocation.class).decode(auxLocationNodes, context)
141 .stream().collect(Collectors.toSet());
142
143 Annotations annotations = extractAnnotations(json, context);
144
145 return new DefaultHost(ProviderId.NONE, id, mac, vlanId,
146 hostLocations, auxHostLocations, ips, innerVlanId,
147 outerTpid, configured, suspended, annotations);
148 }
149
150}