[ONOS-6169] Implement codec for LispAppDataAddress with unit test
Change-Id: I1209bbb5f3e96010ef6df87fe8d0906564942ad4
diff --git a/drivers/lisp/BUCK b/drivers/lisp/BUCK
index 896b6dc..c43fb2e 100644
--- a/drivers/lisp/BUCK
+++ b/drivers/lisp/BUCK
@@ -3,12 +3,18 @@
'//protocols/lisp/api:onos-protocols-lisp-api',
'//protocols/lisp/msg:onos-protocols-lisp-msg',
'//apps/mappingmanagement/api:onos-apps-mappingmanagement-api',
+ '//apps/mappingmanagement/web:onos-apps-mappingmanagement-web',
'//core/store/serializers:onos-core-serializers'
]
TEST_DEPS = [
'//lib:TEST_ADAPTERS',
'//core/api:onos-api-tests',
+ '//lib:jersey-test-framework-core',
+ '//lib:jersey-test-framework-jetty',
+ '//utils/osgi:onlab-osgi-tests',
+ '//web/api:onos-rest-tests',
+ '//apps/mappingmanagement/web:onos-apps-mappingmanagement-web-tests',
]
BUNDLES = [
diff --git a/drivers/lisp/pom.xml b/drivers/lisp/pom.xml
index 1c1f647..419ea16 100644
--- a/drivers/lisp/pom.xml
+++ b/drivers/lisp/pom.xml
@@ -54,6 +54,18 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-app-mapping-web</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-mapping-web</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>${project.version}</version>
</dependency>
@@ -62,6 +74,30 @@
<artifactId>onos-lisp-msg</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-common</artifactId>
+ <scope>test</scope>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-rest</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <type>jar</type>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMappingExtensionCodecRegistrator.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMappingExtensionCodecRegistrator.java
new file mode 100644
index 0000000..adc7e8d
--- /dev/null
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMappingExtensionCodecRegistrator.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.lisp.extensions;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.codec.CodecService;
+import org.onosproject.drivers.lisp.extensions.codec.LispAppDataAddressCodec;
+import org.onosproject.mapping.web.MappingCodecRegistrator;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the JSON codec brokering service for
+ * mapping extension primitives.
+ */
+@Component(immediate = true)
+public class LispMappingExtensionCodecRegistrator extends MappingCodecRegistrator {
+
+ private final Logger log = getLogger(getClass());
+ private MappingCodecRegistrator registrator;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ public CodecService codecService;
+
+ @Activate
+ public void activate() {
+
+ registrator = new MappingCodecRegistrator();
+ registrator.codecService = codecService;
+ registrator.activate();
+
+ codecService.registerCodec(LispAppDataAddress.class, new LispAppDataAddressCodec());
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ codecService.unregisterCodec(LispAppDataAddress.class);
+
+ registrator.deactivate();
+ registrator = null;
+
+ log.info("Stopped");
+ }
+}
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddressCodec.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddressCodec.java
new file mode 100644
index 0000000..9bf3b7f
--- /dev/null
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddressCodec.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.lisp.extensions.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.drivers.lisp.extensions.LispAppDataAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * LISP application data address codec.
+ */
+public final class LispAppDataAddressCodec extends JsonCodec<LispAppDataAddress> {
+
+ protected static final String PROTOCOL = "protocol";
+ protected static final String IP_TOS = "ipTos";
+ protected static final String LOCAL_PORT_LOW = "localPortLow";
+ protected static final String LOCAL_PORT_HIGH = "localPortHigh";
+ protected static final String REMOTE_PORT_LOW = "remotePortLow";
+ protected static final String REMOTE_PORT_HIGH = "remotePortHigh";
+ protected static final String ADDRESS = "address";
+
+ @Override
+ public ObjectNode encode(LispAppDataAddress address, CodecContext context) {
+ checkNotNull(address, "LispAppDataAddress cannot be null");
+
+ final ObjectNode result = context.mapper().createObjectNode()
+ .put(PROTOCOL, address.getProtocol())
+ .put(IP_TOS, address.getIpTos())
+ .put(LOCAL_PORT_LOW, address.getLocalPortLow())
+ .put(LOCAL_PORT_HIGH, address.getLocalPortHigh())
+ .put(REMOTE_PORT_LOW, address.getRemotePortLow())
+ .put(REMOTE_PORT_HIGH, address.getRemotePortHigh());
+
+ if (address.getAddress() != null) {
+ final JsonCodec<MappingAddress> addressCodec =
+ context.codec(MappingAddress.class);
+ ObjectNode addressNode = addressCodec.encode(address.getAddress(), context);
+ result.set(ADDRESS, addressNode);
+ }
+
+ return result;
+ }
+
+ @Override
+ public LispAppDataAddress decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ byte protocol = (byte) json.get(PROTOCOL).asInt();
+ int ipTos = json.get(IP_TOS).asInt();
+ short localPortLow = (short) json.get(LOCAL_PORT_LOW).asInt();
+ short localPortHigh = (short) json.get(LOCAL_PORT_HIGH).asInt();
+ short remotePortLow = (short) json.get(REMOTE_PORT_LOW).asInt();
+ short remotePortHigh = (short) json.get(REMOTE_PORT_HIGH).asInt();
+
+ ObjectNode addressJson = get(json, ADDRESS);
+ MappingAddress mappingAddress = null;
+
+ if (addressJson != null) {
+ final JsonCodec<MappingAddress> addressCodec =
+ context.codec(MappingAddress.class);
+ mappingAddress = addressCodec.decode(addressJson, context);
+ }
+
+ return new LispAppDataAddress.Builder()
+ .withProtocol(protocol)
+ .withIpTos(ipTos)
+ .withLocalPortLow(localPortLow)
+ .withLocalPortHigh(localPortHigh)
+ .withRemotePortLow(remotePortLow)
+ .withRemotePortHigh(remotePortHigh)
+ .withAddress(mappingAddress)
+ .build();
+ }
+}
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/LispMappingExtensionCodecContextAdapter.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/LispMappingExtensionCodecContextAdapter.java
new file mode 100644
index 0000000..8563f2a
--- /dev/null
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/LispMappingExtensionCodecContextAdapter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.lisp.extensions.codec;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.JsonCodec;
+
+/**
+ * An adapter that provides LISP mapping extension codec context.
+ */
+public class LispMappingExtensionCodecContextAdapter implements CodecContext {
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final CodecService manager;
+
+ /**
+ * Constructs a new mock codec context.
+ *
+ * @param manager codec manager
+ */
+ public LispMappingExtensionCodecContextAdapter(CodecService manager) {
+ this.manager = manager;
+ }
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ @Override
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ return manager.getCodec(entityClass);
+ }
+
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ return null;
+ }
+}
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/package-info.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/package-info.java
new file mode 100644
index 0000000..ad1fe70
--- /dev/null
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/codec/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * LISP extensions codec package.
+ */
+package org.onosproject.drivers.lisp.extensions.codec;
\ No newline at end of file
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/package-info.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/package-info.java
index 1c74220..e83dabb 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/package-info.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * Created by guni on 2017. 3. 14..
+ * LISP extensions package.
*/
package org.onosproject.drivers.lisp.extensions;
\ No newline at end of file
diff --git a/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddressCodecTest.java b/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddressCodecTest.java
new file mode 100644
index 0000000..dddb6a0
--- /dev/null
+++ b/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddressCodecTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.lisp.extensions.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.drivers.lisp.extensions.LispAppDataAddress;
+import org.onosproject.drivers.lisp.extensions.LispMappingExtensionCodecRegistrator;
+import org.onosproject.mapping.addresses.MappingAddresses;
+import org.onosproject.mapping.web.codec.MappingAddressJsonMatcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+/**
+ * Unit tests for LispAppDataAddressCodec.
+ */
+public class LispAppDataAddressCodecTest {
+
+ private static final byte PROTOCOL = (byte) 1;
+ private static final int IP_TOS = 1;
+ private static final short LOCAL_PORT_LOW = (short) 1;
+ private static final short LOCAL_PORT_HIGH = (short) 1;
+ private static final short REMOTE_PORT_LOW = (short) 1;
+ private static final short REMOTE_PORT_HIGH = (short) 1;
+ private static final IpPrefix IPV4_PREFIX = IpPrefix.valueOf("10.1.1.0/24");
+
+ private CodecContext context;
+ private JsonCodec<LispAppDataAddress> appDataAddressCodec;
+ private LispMappingExtensionCodecRegistrator registrator;
+
+ /**
+ * Sets up for each test.
+ * Creates a context and fetches the LispAppDataAddress codec.
+ */
+ @Before
+ public void setUp() {
+ CodecManager manager = new CodecManager();
+ registrator = new LispMappingExtensionCodecRegistrator();
+ registrator.codecService = manager;
+ registrator.activate();
+
+ context = new LispMappingExtensionCodecContextAdapter(registrator.codecService);
+ appDataAddressCodec = context.codec(LispAppDataAddress.class);
+ assertThat(appDataAddressCodec, notNullValue());
+ }
+
+ /**
+ * Deactivates the codec registrator.
+ */
+ @After
+ public void tearDown() {
+ registrator.deactivate();
+ }
+
+ /**
+ * Tests encoding of a LispAppDataAddress object.
+ */
+ @Test
+ public void testLispAppDataAddressEncode() {
+
+ LispAppDataAddress address = new LispAppDataAddress.Builder()
+ .withProtocol(PROTOCOL)
+ .withIpTos(IP_TOS)
+ .withLocalPortLow(LOCAL_PORT_LOW)
+ .withLocalPortHigh(LOCAL_PORT_HIGH)
+ .withRemotePortLow(REMOTE_PORT_LOW)
+ .withRemotePortHigh(REMOTE_PORT_HIGH)
+ .withAddress(MappingAddresses.ipv4MappingAddress(IPV4_PREFIX))
+ .build();
+ ObjectNode addressJson = appDataAddressCodec.encode(address, context);
+ assertThat(addressJson, LispAppDataAddressJsonMatcher.matchesAppDataAddress(address));
+ }
+
+ /**
+ * Tests decoding of a LispAppDataAddress JSON object.
+ */
+ @Test
+ public void testLispAppDataAddressDecode() throws IOException {
+ LispAppDataAddress appDataAddress =
+ getLispAppDataAddress("LispAppDataAddress.json");
+
+ assertThat("incorrect protocol value",
+ appDataAddress.getProtocol(), is(PROTOCOL));
+ assertThat("incorrect IP ToS value",
+ appDataAddress.getIpTos(), is(IP_TOS));
+ assertThat("incorrect local port low value",
+ appDataAddress.getLocalPortLow(), is(LOCAL_PORT_LOW));
+ assertThat("incorrect local port high value",
+ appDataAddress.getLocalPortHigh(), is(LOCAL_PORT_HIGH));
+ assertThat("incorrect remote port low value",
+ appDataAddress.getRemotePortLow(), is(REMOTE_PORT_LOW));
+ assertThat("incorrect remote port high value",
+ appDataAddress.getRemotePortHigh(), is(REMOTE_PORT_HIGH));
+ assertThat("incorrect mapping address",
+ appDataAddress.getAddress(),
+ is(MappingAddresses.ipv4MappingAddress(IPV4_PREFIX)));
+ }
+
+ /**
+ * Hamcrest matcher for LispAppDataAddress.
+ */
+ public static final class LispAppDataAddressJsonMatcher
+ extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final LispAppDataAddress address;
+
+ /**
+ * Default constructor.
+ *
+ * @param address LispAppDataAddress object
+ */
+ private LispAppDataAddressJsonMatcher(LispAppDataAddress address) {
+ this.address = address;
+ }
+
+ @Override
+ protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+ // check protocol
+ byte jsonProtocol = (byte) jsonNode.get(LispAppDataAddressCodec.PROTOCOL).asInt();
+ byte protocol = address.getProtocol();
+ if (jsonProtocol != protocol) {
+ description.appendText("protocol was " + jsonProtocol);
+ return false;
+ }
+
+ // check IP type of service
+ int jsonIpTos = jsonNode.get(LispAppDataAddressCodec.IP_TOS).asInt();
+ int ipTos = address.getIpTos();
+ if (jsonIpTos != ipTos) {
+ description.appendText("IP ToS was " + jsonIpTos);
+ return false;
+ }
+
+ // check local port low
+ short jsonLocalPortLow = (short)
+ jsonNode.get(LispAppDataAddressCodec.LOCAL_PORT_LOW).asInt();
+ short localPortLow = address.getLocalPortLow();
+ if (jsonLocalPortLow != localPortLow) {
+ description.appendText("Local port low was " + jsonLocalPortLow);
+ return false;
+ }
+
+ // check local port high
+ short jsonLocalPortHigh = (short)
+ jsonNode.get(LispAppDataAddressCodec.LOCAL_PORT_HIGH).asInt();
+ short localPortHigh = address.getLocalPortHigh();
+ if (jsonLocalPortHigh != localPortHigh) {
+ description.appendText("Local port high was " + jsonLocalPortHigh);
+ return false;
+ }
+
+ // check remote port low
+ short jsonRemotePortLow = (short)
+ jsonNode.get(LispAppDataAddressCodec.REMOTE_PORT_LOW).asInt();
+ short remotePortLow = address.getRemotePortLow();
+ if (jsonRemotePortLow != remotePortLow) {
+ description.appendText("Remote port low was " + jsonRemotePortLow);
+ return false;
+ }
+
+ // check remote port high
+ short jsonRemotePortHigh = (short)
+ jsonNode.get(LispAppDataAddressCodec.REMOTE_PORT_HIGH).asInt();
+ short remotePortHigh = address.getRemotePortHigh();
+ if (jsonRemotePortHigh != remotePortHigh) {
+ description.appendText("Remote port high was " + jsonRemotePortHigh);
+ return false;
+ }
+
+ // check address
+ MappingAddressJsonMatcher addressMatcher =
+ MappingAddressJsonMatcher.matchesMappingAddress(address.getAddress());
+ if (!addressMatcher.matches(jsonNode.get(LispAppDataAddressCodec.ADDRESS))) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(address.toString());
+ }
+
+ /**
+ * Factory to allocate a LispAppDataAddress matcher.
+ *
+ * @param address LispAppDataAddress object we are looking for
+ * @return matcher
+ */
+ public static LispAppDataAddressJsonMatcher matchesAppDataAddress(
+ LispAppDataAddress address) {
+ return new LispAppDataAddressJsonMatcher(address);
+ }
+ }
+
+ /**
+ * Reads in a LispAppDataAddress from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded LispAppDataAddress
+ * @throws IOException if processing the resource fails
+ */
+ private LispAppDataAddress getLispAppDataAddress(String resourceName) throws IOException {
+ InputStream jsonStream = LispAppDataAddressCodecTest.class.getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ LispAppDataAddress nextObjective = appDataAddressCodec.decode((ObjectNode) json, context);
+ assertThat(nextObjective, notNullValue());
+ return nextObjective;
+ }
+}
diff --git a/drivers/lisp/src/test/resources/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddress.json b/drivers/lisp/src/test/resources/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddress.json
new file mode 100644
index 0000000..b00e32d
--- /dev/null
+++ b/drivers/lisp/src/test/resources/org/onosproject/drivers/lisp/extensions/codec/LispAppDataAddress.json
@@ -0,0 +1,12 @@
+{
+ "protocol": 1,
+ "ipTos": 1,
+ "localPortLow": 1,
+ "localPortHigh": 1,
+ "remotePortLow": 1,
+ "remotePortHigh": 1,
+ "address": {
+ "type": "IPV4",
+ "ipv4": "10.1.1.0/24"
+ }
+}
\ No newline at end of file