[VOL-3661] PPPoE IA application - initial commit
Change-Id: Idaf23f8736cba955fe8a3049b8fc9c85b3cd3ab9
Signed-off-by: Gustavo Silva <gsilva@furukawalatam.com>
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100644
index 0000000..96631bb
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2021-present Open Networking Foundation
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>pppoeagent</artifactId>
+ <groupId>org.opencord</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>pppoeagent-api</artifactId>
+ <packaging>bundle</packaging>
+ <description>PPPoE Intermediate Agent API</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${onos.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${onos.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opencord</groupId>
+ <artifactId>sadis-api</artifactId>
+ <version>${sadis.api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-cli</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/api/src/main/java/org/opencord/pppoeagent/PPPoEDVendorSpecificTag.java b/api/src/main/java/org/opencord/pppoeagent/PPPoEDVendorSpecificTag.java
new file mode 100644
index 0000000..8605637
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/PPPoEDVendorSpecificTag.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+/**
+ * Represents the "Vendor-Specific" PPPoED tag.
+ * This class is used by the PPPoE agent in order to read/build the tag that carries the
+ * vendor-id, circuit-id and remote-id information, which are attached to the upstrem packets.
+ */
+public class PPPoEDVendorSpecificTag {
+ public static final int BBF_IANA_VENDOR_ID = 3561;
+ private static final byte CIRCUIT_ID_OPTION = 1;
+ private static final byte REMOTE_ID_OPTION = 2;
+
+ private int vendorId = BBF_IANA_VENDOR_ID;
+ private String circuitId = null;
+ private String remoteId = null;
+
+ /**
+ * Creates an empty Vendor-Specific tag object.
+ *
+ */
+ public PPPoEDVendorSpecificTag() {
+ }
+
+ /**
+ * Creates a new Vendor-Specific tag object.
+ *
+ * @param circuitId circuit-id information
+ * @param remoteId remote-id information
+ */
+ public PPPoEDVendorSpecificTag(String circuitId, String remoteId) {
+ this.circuitId = circuitId;
+ this.remoteId = remoteId;
+ }
+
+ /**
+ * Sets the vendor-id.
+ *
+ * @param value vendor-id to be set.
+ */
+ public void setVendorId(int value) {
+ this.vendorId = value;
+ }
+
+ /**
+ * Gets the vendor-id.
+ *
+ * @return the vendor-id.
+ */
+ public Integer getVendorId() {
+ return this.vendorId;
+ }
+
+ /**
+ * Sets the circuit-id.
+ *
+ * @param value circuit-id to be set.
+ */
+ public void setCircuitId(String value) {
+ this.circuitId = value;
+ }
+
+ /**
+ * Gets the circuit-id.
+ *
+ * @return the circuit-id.
+ */
+ public String getCircuitId() {
+ return this.circuitId;
+ }
+
+ /**
+ * Sets the remote-id.
+ *
+ * @param value remote-id to be set.
+ */
+ public void setRemoteId(String value) {
+ this.remoteId = value;
+ }
+
+ /**
+ * Gets the remote-id.
+ *
+ * @return the remote-id.
+ */
+ public String getRemoteId() {
+ return this.remoteId;
+ }
+
+ /**
+ * Returns the representation of the PPPoED vendor-specific tag as byte array.
+ * @return returns byte array
+ */
+ public byte[] toByteArray() {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ byte[] bytes = ByteBuffer.allocate(4).putInt(this.vendorId).array();
+ buf.write(bytes, 0, bytes.length);
+
+ // Add sub option if set
+ if (circuitId != null) {
+ buf.write(CIRCUIT_ID_OPTION);
+ buf.write((byte) circuitId.length());
+ bytes = circuitId.getBytes(StandardCharsets.UTF_8);
+ buf.write(bytes, 0, bytes.length);
+ }
+
+ // Add sub option if set
+ if (remoteId != null) {
+ buf.write(REMOTE_ID_OPTION);
+ buf.write((byte) remoteId.length());
+ bytes = remoteId.getBytes(StandardCharsets.UTF_8);
+ buf.write(bytes, 0, bytes.length);
+ }
+
+ return buf.toByteArray();
+ }
+
+ /**
+ * Returns a PPPoEDVendorSpecificTag object from a byte array.
+ * @param data byte array data to convert to PPPoEDVendorSpecificTag object.
+ * @return vendor specific tag from given byte array.
+ * */
+ public static PPPoEDVendorSpecificTag fromByteArray(byte[] data) {
+ int position = 0;
+ final int vendorIdLength = 4;
+
+ PPPoEDVendorSpecificTag vendorSpecificTag = new PPPoEDVendorSpecificTag();
+
+ if (data.length < vendorIdLength) {
+ return vendorSpecificTag;
+ }
+
+ int vId = ByteBuffer.wrap(data, position, vendorIdLength).getInt();
+ vendorSpecificTag.setVendorId(vId);
+
+ position += vendorIdLength;
+
+ while (data.length > position) {
+ byte code = data[position];
+ position++;
+
+ if (data.length < position) {
+ break;
+ }
+
+ int length = (int) data[position];
+ position++;
+
+ if (data.length < (position + length)) {
+ break;
+ }
+
+ String clvString = new String(Arrays.copyOfRange(data, position, length + position),
+ StandardCharsets.UTF_8);
+
+ position += length;
+
+ if (code == CIRCUIT_ID_OPTION) {
+ vendorSpecificTag.setCircuitId(clvString);
+ } else if (code == REMOTE_ID_OPTION) {
+ vendorSpecificTag.setRemoteId(clvString);
+ }
+ }
+
+ return vendorSpecificTag;
+ }
+}
diff --git a/api/src/main/java/org/opencord/pppoeagent/PppoeAgentEvent.java b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentEvent.java
new file mode 100644
index 0000000..ec491b1
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentEvent.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.ConnectPoint;
+/**
+ * PppoeAgent event.
+ */
+public class PppoeAgentEvent extends AbstractEvent<PppoeAgentEvent.Type, PppoeSessionInfo> {
+ private final ConnectPoint connectPoint;
+ private final MacAddress subscriberMacAddress;
+ private final String counterName;
+ private final Long counterValue;
+ private final String subscriberId;
+
+ // Session terminates may have an error tag with a 'reason' message, this field is meant to track that info.
+ private final String reason;
+
+ public static final String GLOBAL_COUNTER = "global";
+
+ /**
+ * Type of the event.
+ */
+ public enum Type {
+ /**
+ * PPPoE discovery negotiation started.
+ */
+ START,
+
+ /**
+ * PPPoE server is responding to client packets - session is under negotiation.
+ */
+ NEGOTIATION,
+
+ /**
+ * PPPoE discovery negotiation is complete, session is established.
+ */
+ SESSION_ESTABLISHED,
+
+ /**
+ * Client or server event to indicate end of a session.
+ */
+ TERMINATE,
+
+ /**
+ * PPPoE stats update.
+ */
+ STATS_UPDATE,
+
+ /**
+ * Circuit-id mismatch.
+ */
+ INVALID_CID,
+
+ /**
+ * Default value for unknown event.
+ */
+ UNKNOWN
+ }
+
+
+ /**
+ * Creates a new PPPoE counters event.
+ *
+ * @param type type of the event
+ * @param sessionInfo session info
+ * @param counterName name of specific counter
+ * @param counterValue value of specific counter
+ * @param subscriberMacAddress the subscriber MAC address information
+ * @param subscriberId id of subscriber
+ */
+ public PppoeAgentEvent(Type type, PppoeSessionInfo sessionInfo, String counterName, Long counterValue,
+ MacAddress subscriberMacAddress, String subscriberId) {
+ super(type, sessionInfo);
+ this.counterName = counterName;
+ this.counterValue = counterValue;
+ this.subscriberMacAddress = subscriberMacAddress;
+ this.subscriberId = subscriberId;
+ this.connectPoint = null;
+ this.reason = null;
+ }
+
+ /**
+ * Creates a new generic PPPoE event.
+ *
+ * @param type type of the event
+ * @param sessionInfo session info
+ * @param connectPoint connect point the client is on
+ * @param subscriberMacAddress the subscriber MAC address information
+ */
+ public PppoeAgentEvent(Type type, PppoeSessionInfo sessionInfo, ConnectPoint connectPoint,
+ MacAddress subscriberMacAddress) {
+ super(type, sessionInfo);
+ this.connectPoint = connectPoint;
+ this.subscriberMacAddress = subscriberMacAddress;
+ this.counterName = null;
+ this.counterValue = null;
+ this.subscriberId = null;
+ this.reason = null;
+ }
+
+ /**
+ * Creates a new PPPOE event with a reason (PADT packets may have a 'reason' field).
+ *
+ * @param type type of the event
+ * @param sessionInfo session info
+ * @param connectPoint connect point the client is on
+ * @param subscriberMacAddress the subscriber MAC address information
+ * @param reason events such TERMINATE may have reason field
+ */
+ public PppoeAgentEvent(Type type, PppoeSessionInfo sessionInfo, ConnectPoint connectPoint,
+ MacAddress subscriberMacAddress, String reason) {
+ super(type, sessionInfo);
+ this.connectPoint = connectPoint;
+ this.subscriberMacAddress = subscriberMacAddress;
+ this.reason = reason;
+ this.counterName = null;
+ this.counterValue = null;
+ this.subscriberId = null;
+ }
+
+
+ /**
+ * Gets the PPPoE client connect point.
+ *
+ * @return connect point
+ */
+ public ConnectPoint getConnectPoint() {
+ return connectPoint;
+ }
+
+ /**
+ * Gets the subscriber MAC address.
+ *
+ * @return the MAC address from subscriber
+ */
+ public MacAddress getSubscriberMacAddress() {
+ return subscriberMacAddress;
+ }
+
+ /**
+ * Gets the event reason.
+ *
+ * @return event reason.
+ */
+ public String getReason() {
+ return reason;
+ }
+
+ /**
+ * Gets the counter name.
+ *
+ * @return counter name.
+ */
+ public String getCounterName() {
+ return counterName;
+ }
+
+ /**
+ * Gets the counter value.
+ *
+ * @return counter value.
+ */
+ public Long getCounterValue() {
+ return counterValue;
+ }
+
+ /**
+ * Gets the subscriber identifier information.
+ *
+ * @return the Id from subscriber
+ */
+ public String getSubscriberId() {
+ return subscriberId;
+ }
+
+ @Override
+ public String toString() {
+ return "PppoeAgentEvent{" +
+ "connectPoint=" + connectPoint +
+ ", subscriberMacAddress=" + subscriberMacAddress +
+ ", reason='" + reason + '\'' +
+ ", counterName=" + counterName +
+ ", counterValue=" + counterValue +
+ ", subscriberId='" + subscriberId + '\'' +
+ '}';
+ }
+}
diff --git a/api/src/main/java/org/opencord/pppoeagent/PppoeAgentListener.java b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentListener.java
new file mode 100644
index 0000000..03d3501
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentListener.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for PPPoE agents events.
+ */
+public interface PppoeAgentListener extends EventListener<PppoeAgentEvent> {
+}
diff --git a/api/src/main/java/org/opencord/pppoeagent/PppoeAgentService.java b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentService.java
new file mode 100644
index 0000000..616607a
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent;
+
+import java.util.Map;
+import org.onlab.packet.MacAddress;
+import org.onosproject.event.ListenerService;
+
+/**
+ * PPPoE Agent service.
+ */
+public interface PppoeAgentService extends
+ ListenerService<PppoeAgentEvent, PppoeAgentListener> {
+ Map<MacAddress, PppoeSessionInfo> getSessionsMap();
+
+ /**
+ * Removes all PPPoE agent session entries.
+ */
+ void clearSessionsMap();
+}
diff --git a/api/src/main/java/org/opencord/pppoeagent/PppoeAgentStoreDelegate.java b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentStoreDelegate.java
new file mode 100644
index 0000000..3d2f72e
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/PppoeAgentStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent;
+
+import org.onosproject.store.StoreDelegate;
+/**
+ * Store delegate for PPPoE Agent store.
+ */
+public interface PppoeAgentStoreDelegate extends StoreDelegate<PppoeAgentEvent> {
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/PppoeSessionInfo.java b/api/src/main/java/org/opencord/pppoeagent/PppoeSessionInfo.java
new file mode 100644
index 0000000..81d7d09
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/PppoeSessionInfo.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.PPPoED;
+import org.onosproject.net.ConnectPoint;
+import org.opencord.sadis.SubscriberAndDeviceInformation;
+
+/**
+ * PppoeAgent session information.
+ */
+public class PppoeSessionInfo {
+ private ConnectPoint clientCp;
+ private ConnectPoint serverCp;
+ private Byte packetCode;
+ private short sessionId;
+ SubscriberAndDeviceInformation subscriber;
+ MacAddress clientMac;
+
+ /**
+ * Creates a new PPPoE session information object.
+ *
+ * @param clientCp PPPoE client connect-point.
+ * @param serverCp PPPoE server connect-point.
+ * @param packetCode The packet code of last PPPOED received message.
+ * @param sessionId session-id value.
+ * @param subscriber Sadis object of PPPoE client.
+ * @param clientMac MAC address of PPPoE client.
+ */
+ public PppoeSessionInfo(ConnectPoint clientCp, ConnectPoint serverCp, Byte packetCode, short sessionId,
+ SubscriberAndDeviceInformation subscriber, MacAddress clientMac) {
+ this.clientCp = clientCp;
+ this.serverCp = serverCp;
+ this.packetCode = packetCode;
+ this.sessionId = sessionId;
+ this.subscriber = subscriber;
+ this.clientMac = clientMac;
+ }
+
+ /**
+ * Creates an empty PPPoE session information object.
+ */
+ public PppoeSessionInfo() {
+ }
+
+ /**
+ * Gets the PPPoE client connect-point.
+ *
+ * @return client connect-point.
+ */
+ public ConnectPoint getClientCp() {
+ return clientCp;
+ }
+
+ /**
+ * Sets the PPPoE client connect-point.
+ *
+ * @param clientCp client connect-point.
+ */
+ public void setClientCp(ConnectPoint clientCp) {
+ this.clientCp = clientCp;
+ }
+
+ /**
+ * Gets the PPPoE server connect-point.
+ *
+ * @return server connect-point.
+ */
+ public ConnectPoint getServerCp() {
+ return serverCp;
+ }
+
+ /**
+ * Sets the PPPoE server connect-point.
+ *
+ * @param serverCp server connect-point.
+ */
+ public void setServerCp(ConnectPoint serverCp) {
+ this.serverCp = serverCp;
+ }
+
+ /**
+ * Gets the PPPoE client SADIS object.
+ *
+ * @return client SADIS object.
+ */
+ public SubscriberAndDeviceInformation getSubscriber() {
+ return subscriber;
+ }
+
+ /**
+ * Sets the PPPoE client SADIS object.
+ *
+ * @param subscriber client SADIS object.
+ */
+ public void setSubscriber(SubscriberAndDeviceInformation subscriber) {
+ this.subscriber = subscriber;
+ }
+
+ /**
+ * Gets the PPPoE client MAC address.
+ *
+ * @return client MAC address.
+ */
+ public MacAddress getClientMac() {
+ return clientMac;
+ }
+
+ /**
+ * Sets the PPPoE client MAC address.
+ *
+ * @param clientMac MAC address.
+ */
+ public void setClientMac(MacAddress clientMac) {
+ this.clientMac = clientMac;
+ }
+
+ /**
+ * Gets the PPPoE session-id.
+ *
+ * @return PPPoE session-id.
+ */
+ public short getSessionId() {
+ return sessionId;
+ }
+
+ /**
+ * Sets the PPPoE session-id.
+ *
+ * @param sessionId PPPoE session-id.
+ */
+ public void setSessionId(short sessionId) {
+ this.sessionId = sessionId;
+ }
+
+ /**
+ * Gets the PPPoED packet code of the last received message.
+ *
+ * @return last received PPPoED code.
+ */
+ public Byte getPacketCode() {
+ return packetCode;
+ }
+
+ /**
+ * Sets the PPPoED packet code from the last received message.
+ *
+ * @param packetCode PPPoED packet code.
+ */
+ public void setPacketCode(byte packetCode) {
+ this.packetCode = packetCode;
+ }
+
+ /**
+ * Gets a string to represent the current session state based on the last received packet code.
+ * This function uses conveniently the name of some PPPoEAgentEvent types to represent the state.
+ *
+ * @return PPPOE session state.
+ */
+ public String getCurrentState() {
+ PPPoED.Type lastReceivedPkt = PPPoED.Type.getTypeByValue(this.packetCode);
+ switch (lastReceivedPkt) {
+ case PADI:
+ return PppoeAgentEvent.Type.START.name();
+ case PADR:
+ case PADO:
+ return PppoeAgentEvent.Type.NEGOTIATION.name();
+ case PADS:
+ return PppoeAgentEvent.Type.SESSION_ESTABLISHED.name();
+ case PADT:
+ // This case might never happen (entry is being removed on PADT messages).
+ return PppoeAgentEvent.Type.TERMINATE.name();
+ default:
+ return PppoeAgentEvent.Type.UNKNOWN.name();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "PppoeSessionInfo{" +
+ "clientCp=" + clientCp +
+ ", serverCp=" + serverCp +
+ ", packetCode=" + packetCode +
+ ", sessionId=" + sessionId +
+ ", subscriber=" + subscriber +
+ ", clientMac=" + clientMac +
+ '}';
+ }
+}
+
diff --git a/api/src/main/java/org/opencord/pppoeagent/package-info.java b/api/src/main/java/org/opencord/pppoeagent/package-info.java
new file mode 100644
index 0000000..22b3633
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * API for PPPoE agent.
+ */
+package org.opencord.pppoeagent;
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdBuilder.java b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdBuilder.java
new file mode 100644
index 0000000..f955704
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdBuilder.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.Range;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceService;
+import org.opencord.sadis.BaseInformationService;
+import org.opencord.sadis.SubscriberAndDeviceInformation;
+import org.onosproject.net.Device;
+import org.opencord.sadis.UniTagInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Circuit-id builder util.
+ */
+public class CircuitIdBuilder {
+ //#region Circuit-id Builder
+ private CircuitIdConfig circuitIdConfig;
+ private DeviceService deviceService;
+ private BaseInformationService<SubscriberAndDeviceInformation> subsService;
+ private ConnectPoint connectPoint;
+ private String[] exclusiveExpressions;
+ private Map<CircuitIdFieldName, String> customSeparators;
+ private UniTagInformation uniTagInformation;
+
+ private final ArrayList<CircuitIdField> availableFields = new ArrayList<>(
+ Arrays.asList(new CircuitIdAccessNodeIdentifier(),
+ new CircuitIdNetworkTechnology(),
+ new CircuitIdSlot(),
+ new CircuitIdPort(),
+ new CircuitIdOnuSerialNumber(),
+ new CircuitIdUniPortNumber(),
+ new CircuitIdSvId(),
+ new CircuitIdCvId())
+ );
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * Creates a new CircuitId builder with default configuration.
+ */
+ public CircuitIdBuilder() {
+ // Instantiate the circuit-id config Object.
+ circuitIdConfig = new CircuitIdConfig();
+ circuitIdConfig.setSeparator("/");
+ // This is a default list with exclusive expressions to validate the field value.
+ exclusiveExpressions = new String[] {circuitIdConfig.getSeparator()};
+
+ // At the end we set the default field list - in the future these fields will be defined by the operator.
+ circuitIdConfig.setFieldListWithDefault(availableFields);
+ customSeparators = new HashMap<>();
+ }
+
+ /**
+ * Sets the connect-point.
+ *
+ * @param value connect-point.
+ * @return circuit-id builder.
+ */
+ public CircuitIdBuilder setConnectPoint(ConnectPoint value) {
+ this.connectPoint = value;
+ return this;
+ }
+
+ /**
+ * Sets the device service.
+ *
+ * @param value device service.
+ * @return circuit-id builder.
+ */
+ public CircuitIdBuilder setDeviceService(DeviceService value) {
+ this.deviceService = value;
+ return this;
+ }
+
+ /**
+ * Sets the SADIS service.
+ *
+ * @param value SADIS service.
+ * @return circuit-id builder.
+ */
+ public CircuitIdBuilder setSubsService(BaseInformationService<SubscriberAndDeviceInformation> value) {
+ this.subsService = value;
+ return this;
+ }
+
+ /**
+ * Sets the UniTag information.
+ *
+ * @param value UniTag information.
+ * @return circuit-id builder.
+ */
+ public CircuitIdBuilder setUniTagInformation(UniTagInformation value) {
+ this.uniTagInformation = value;
+ return this;
+ }
+
+ /**
+ * Adds a custom separator.
+ *
+ * @param field the circuit-id field associated to the custom separator.
+ * @param separator the custom separator to be added.
+ * @return circuit-id builder.
+ */
+ public CircuitIdBuilder addCustomSeparator(CircuitIdFieldName field, String separator) {
+ if (!circuitIdConfig.getSeparator().equals(separator)) {
+ customSeparators.put(field, separator);
+ } else {
+ log.warn("Not defining custom separator '{}' for {} field since it's equals to the configured separator.",
+ separator, field.name());
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the custom separators.
+ *
+ * @return a map with the circuit-id fields and its custom separators.
+ */
+ public Map<CircuitIdFieldName, String> getCustomSeparators() {
+ return customSeparators;
+ }
+
+ /**
+ * Gets the circuit-id configuration object.
+ *
+ * @return the configuration for circuit-id builder.
+ */
+ public CircuitIdConfig getCircuitIdConfig() {
+ return this.circuitIdConfig;
+ }
+
+ /**
+ * Sets the circuit-id configuration.
+ *
+ * @param fieldNameList the list of desired fields.
+ * @return circuit-id builder.
+ */
+ public CircuitIdBuilder setCircuitIdConfig(ArrayList<CircuitIdFieldName> fieldNameList) {
+ circuitIdConfig.setFieldList(fieldNameList, availableFields);
+ return this;
+ }
+
+ /**
+ * Generates the circuit-id based on the provided configuration and default/custom separators.
+ *
+ * @return circuit-id.
+ */
+ public String build() {
+ String circuitId = "";
+
+ // Get the field list.
+ ArrayList<CircuitIdField> fieldList = circuitIdConfig.getFieldList();
+
+ // Check if it's valid.
+ if (fieldList == null || fieldList.size() <= 0) {
+ log.error("Failed to build the circuit Id: there's no entries in the field list.");
+ return "";
+ }
+
+ // This list is filtered to ignore prefix fields.
+ ArrayList<CircuitIdField> filteredFieldList = fieldList;
+
+ // Go throughout the field list to build the string.
+ for (int i = 0; i < filteredFieldList.size(); i++) {
+ CircuitIdField field = filteredFieldList.get(i);
+
+ String value = "";
+ try {
+ value = field.build();
+ } catch (MissingParameterException | FieldValidationException e) {
+ log.error(e.getMessage());
+ return "";
+ }
+
+ // Concat the obtained value with the rest of id.
+ circuitId = circuitId.concat(value);
+
+ // If this is not the last "for" iteration, isolate with the separator.
+ if (i != (filteredFieldList.size() - 1)) {
+ String separator = customSeparators.containsKey(field.getFieldName()) ?
+ customSeparators.get(field.getFieldName()) : circuitIdConfig.getSeparator();
+
+ circuitId = circuitId.concat(separator);
+ }
+ }
+ // At the end, it returns the fully built string.
+ return circuitId;
+ }
+ //#endregion
+
+ //#region Field Classes
+ private SubscriberAndDeviceInformation getSadisEntry() {
+ Port p = deviceService.getPort(connectPoint);
+ String subscriber = p.annotations().value(AnnotationKeys.PORT_NAME);
+ return subsService.get(subscriber);
+ }
+
+ private class CircuitIdAccessNodeIdentifier extends CircuitIdField {
+ CircuitIdAccessNodeIdentifier() {
+ this.setFieldName(CircuitIdFieldName.AcessNodeIdentifier)
+ .setIsNumber(false)
+ .setExclusiveExpressions(exclusiveExpressions);
+ }
+
+ @Override
+ String build() throws MissingParameterException,
+ FieldValidationException {
+ // This field must be the serial number of the OLT which the packet came from.
+ // So we try to recover this information using the device Id of the connect point.
+ Device device = deviceService.getDevice(connectPoint.deviceId());
+
+ if (device == null) {
+ String errorMsg = String.format("Device not found at device service: %s.", connectPoint.deviceId());
+ throw new MissingParameterException(errorMsg);
+ }
+
+ String accessNodeId = device.serialNumber();
+
+ if (isValid(accessNodeId)) {
+ return accessNodeId;
+ } else {
+ throw new FieldValidationException(this, accessNodeId);
+ }
+ }
+ }
+
+ private static class CircuitIdSlot extends CircuitIdField {
+ CircuitIdSlot() {
+ this.setFieldName(CircuitIdFieldName.Slot)
+ .setIsNumber(true)
+ .setMaxLength(2)
+ .setRange(Range.between(0L, 99L));
+ }
+
+ @Override
+ String build() {
+ // At first, this will be hard-coded as "0". But this may change in future implementation.
+ return "0";
+ }
+ }
+
+ private class CircuitIdPort extends CircuitIdField {
+ CircuitIdPort() {
+ this.setFieldName(CircuitIdFieldName.Port)
+ .setIsNumber(true)
+ .setMaxLength(3)
+ .setRange(Range.between(1L, 256L));
+ }
+
+ @Override
+ String build() throws MissingParameterException,
+ FieldValidationException {
+ String port = "";
+
+ // If there's no connect-point we can't build this field.
+ if (connectPoint == null) {
+ String errorMsg = "ConnectPoint not passed to circuit-id builder - can't build PORT field.";
+ throw new MissingParameterException(errorMsg);
+ }
+
+ long connectPointPort = connectPoint.port().toLong();
+ int ponPort = ((int) connectPointPort >> 12) + 1;
+
+ port = String.valueOf(ponPort);
+ if (isValid(port)) {
+ return port;
+ } else {
+ throw new FieldValidationException(this, port);
+ }
+ }
+ }
+
+ private class CircuitIdOnuSerialNumber extends CircuitIdField {
+ CircuitIdOnuSerialNumber() {
+ this.setFieldName(CircuitIdFieldName.OnuSerialNumber)
+ .setIsNumber(false)
+ .setExclusiveExpressions(exclusiveExpressions);
+ }
+
+ @Override
+ String build() throws MissingParameterException,
+ FieldValidationException {
+
+ if (deviceService == null) {
+ String errorMsg = "Device service not passed to circuit-id builder - can't build ONU SN field.";
+ throw new MissingParameterException(errorMsg);
+ }
+
+ Port p = deviceService.getPort(connectPoint);
+ String onuSn = p.annotations().value(AnnotationKeys.PORT_NAME);
+
+ // The reason of the following block is that in some cases, the UNI port number can be
+ // appended in the ONU serial number. So it's required to remove it.
+ CircuitIdUniPortNumber uniPortNumberField = new CircuitIdUniPortNumber();
+ String uniPortNumber = uniPortNumberField.build();
+
+ if (uniPortNumberField.isValid(uniPortNumber)) {
+ // Build the suffix it shouldn't have based on the UNI port number.
+ uniPortNumber = "-" + (Integer.parseInt(uniPortNumber));
+
+ // Checks if the serial number contains this suffix.
+ if (onuSn.substring(onuSn.length() - uniPortNumber.length()).equals(uniPortNumber)) {
+ // Remove it if this is the case.
+ onuSn = onuSn.substring(0, onuSn.indexOf(uniPortNumber));
+ }
+
+ } else {
+ log.debug("Failed to get the UNI port number, the ONU serial number could be wrong;");
+ }
+
+
+ if (isValid(onuSn)) {
+ return onuSn;
+ } else {
+ throw new FieldValidationException(this, onuSn);
+ }
+ }
+ }
+
+ private class CircuitIdUniPortNumber extends CircuitIdField {
+ CircuitIdUniPortNumber() {
+ this.setFieldName(CircuitIdFieldName.UniPortNumber)
+ .setIsNumber(true)
+ .setMaxLength(2)
+ .setRange(Range.between(1L, 99L));
+ }
+
+ @Override
+ String build() throws MissingParameterException,
+ FieldValidationException {
+ // If there's no connect-point we can't build this field.
+ if (connectPoint == null) {
+ String errorMsg = "ConnectPoint not passed to circuit-id builder - can't build UNI PORT NUMBER field.";
+ throw new MissingParameterException(errorMsg);
+ }
+
+ long connectPointPort = connectPoint.port().toLong();
+ int uniPortNumber = ((int) connectPointPort & 0xF) + 1;
+
+ String uniPortString = String.valueOf(uniPortNumber);
+
+ if (isValid(uniPortString)) {
+ return uniPortString;
+ } else {
+ throw new FieldValidationException(this, uniPortString);
+ }
+ }
+ }
+
+ private class CircuitIdSvId extends CircuitIdField {
+ CircuitIdSvId() {
+ this.setFieldName(CircuitIdFieldName.SvID)
+ .setIsNumber(true)
+ .setMaxLength(4)
+ .setRange(Range.between(0L, 4095L));
+ }
+
+ @Override
+ String build() throws MissingParameterException,
+ FieldValidationException {
+ if (uniTagInformation == null) {
+ String errorMsg = String.format("UNI TAG info not found for %s while looking for S-TAG.", connectPoint);
+ throw new MissingParameterException(errorMsg);
+ }
+
+ String sVid = uniTagInformation.getPonSTag().toString();
+ if (isValid(sVid)) {
+ return sVid;
+ } else {
+ throw new FieldValidationException(this, sVid);
+ }
+ }
+ }
+
+ private class CircuitIdCvId extends CircuitIdField {
+ CircuitIdCvId() {
+ this.setFieldName(CircuitIdFieldName.CvID)
+ .setIsNumber(true)
+ .setMaxLength(4)
+ .setRange(Range.between(0L, 4095L));
+ }
+
+ @Override
+ String build() throws MissingParameterException,
+ FieldValidationException {
+ if (uniTagInformation == null) {
+ String errorMsg = String.format("UNI TAG info not found for %s looking for C-TAG", connectPoint);
+ throw new MissingParameterException(errorMsg);
+ }
+
+ String cVid = uniTagInformation.getPonCTag().toString();
+ if (isValid(cVid)) {
+ return cVid;
+ } else {
+ throw new FieldValidationException(this, cVid);
+ }
+ }
+ }
+
+ private class CircuitIdNetworkTechnology extends CircuitIdField {
+ CircuitIdNetworkTechnology() {
+ this.setFieldName(CircuitIdFieldName.NetworkTechnology)
+ .setIsNumber(false)
+ .setExclusiveExpressions(exclusiveExpressions);
+ }
+
+ // For now this is fixed.
+ @Override
+ String build() {
+ return "xpon";
+ }
+ }
+ //#endregion
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdConfig.java b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdConfig.java
new file mode 100644
index 0000000..3efc369
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdConfig.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Configuration options for circuit-id builder.
+ */
+public class CircuitIdConfig {
+ private String separator;
+ private ArrayList<CircuitIdField> fieldList;
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ // This list defines the default configuration for circuit-id.
+ // Circuit-id will follow the same order of this list.
+ private final ArrayList<CircuitIdFieldName> defaultFieldSelection = new ArrayList<>(
+ Arrays.asList(CircuitIdFieldName.AcessNodeIdentifier,
+ CircuitIdFieldName.NetworkTechnology,
+ CircuitIdFieldName.Slot,
+ CircuitIdFieldName.Port,
+ CircuitIdFieldName.OnuSerialNumber,
+ CircuitIdFieldName.UniPortNumber,
+ CircuitIdFieldName.SvID,
+ CircuitIdFieldName.CvID)
+ );
+
+ /**
+ * Gets the default separator.
+ *
+ * @return separator.
+ */
+ public String getSeparator() {
+ return separator;
+ }
+
+ /**
+ * Sets the default separator.
+ *
+ * @param value separator.
+ * @return circuit-id configuration object.
+ */
+ public CircuitIdConfig setSeparator(String value) {
+ this.separator = value;
+ return this;
+ }
+
+ /**
+ * Gets the circuit-id field list.
+ *
+ * @return circuit-id field list.
+ */
+ public ArrayList<CircuitIdField> getFieldList() {
+ return fieldList;
+ }
+
+ private CircuitIdConfig setFieldList(ArrayList<CircuitIdField> value) {
+ this.fieldList = value;
+ return this;
+ }
+
+ /**
+ * Sets the field list considering a list of supported fields.
+ *
+ * @param fieldSelection desired field list.
+ * @param availableFields available field list.
+ * @return circuit-id config object.
+ */
+ public CircuitIdConfig setFieldList(ArrayList<CircuitIdFieldName> fieldSelection,
+ ArrayList<CircuitIdField> availableFields) {
+ // Find out the fields based on the field selection for this config.
+ ArrayList<CircuitIdField> value = fieldSelection
+ .stream()
+ .map(fieldName -> availableFields
+ .stream()
+ .filter(field -> field.getFieldName()
+ .equals(fieldName))
+ .findFirst()
+ .orElse(null))
+ .collect(Collectors.toCollection(ArrayList::new));
+
+ boolean foundAllFields = value.stream().noneMatch(Objects::isNull);
+
+ // Ignores if it found all fields.
+ if (!foundAllFields) {
+ // Otherwise, it log and remove null entries.
+ log.warn("Some desired fields are not available.");
+ value.removeAll(Collections.singleton(null));
+ }
+
+ setFieldList(value);
+ return this;
+ }
+
+ /**
+ * Sets the field list with the default values considering a list of available fields.
+ *
+ * @param availableFields available field list.
+ * @return circuit-id config object.
+ */
+ public CircuitIdConfig setFieldListWithDefault(ArrayList<CircuitIdField> availableFields) {
+ return setFieldList(this.getDefaultFieldSelection(), availableFields);
+ }
+
+ private ArrayList<CircuitIdFieldName> getDefaultFieldSelection() {
+ return defaultFieldSelection;
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdField.java b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdField.java
new file mode 100644
index 0000000..f44aaf3
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdField.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent.util;
+
+import org.apache.commons.lang3.Range;
+
+import java.util.Arrays;
+
+/**
+ * Circuit-id field abstract model.
+ * This is a model that shouldn't be instantiated, for new fields please create a class that extends this one.
+ */
+public abstract class CircuitIdField {
+ // Definitions to perform general validation.
+ private Integer maxLength;
+ private boolean isRangeLike;
+ private Range<Long> range;
+ private CircuitIdFieldName fieldName;
+ private boolean isNumber;
+
+ // This is used to avoid conflicts in string values,
+ // Example: when a field value contains the same char as the separator.
+ private String[] exclusiveExpressions;
+
+ CircuitIdFieldName getFieldName() {
+ return this.fieldName;
+ }
+
+ CircuitIdField setFieldName(CircuitIdFieldName value) {
+ this.fieldName = value;
+ return this;
+ }
+
+ Integer getMaxLength() {
+ return this.maxLength;
+ }
+
+ CircuitIdField setMaxLength(int value) {
+ this.maxLength = value;
+ return this;
+ }
+
+ Range<Long> getRange() {
+ return isRangeLike ? range : null;
+ }
+
+ CircuitIdField setRange(Range<Long> value) {
+ this.isRangeLike = value != null;
+ this.range = value;
+ return this;
+ }
+
+ CircuitIdField setIsNumber(boolean value) {
+ this.isNumber = value;
+ return this;
+ }
+
+ CircuitIdField setExclusiveExpressions(String[] value) {
+ this.exclusiveExpressions = value;
+ return this;
+ }
+
+ // It's recommended to call this method after building the field value, this will
+ // perform general validations based on the definitions of the field (range, maxLength, isNumber, (...))
+ boolean isValid(String value) {
+ // This is the flag is the output of the assertions.
+ boolean challenge = true;
+
+ if (value == null) {
+ return false;
+ }
+
+ // This code block is only in the case we're validating a number:
+ long longValue = 0L;
+ if (isNumber) {
+ try {
+ // We try to parse the value.
+ longValue = Long.parseLong(value);
+ // If there's a range defined.
+ if (isRangeLike) {
+ // We verify if the value is at the defined range.
+ challenge &= range.contains(longValue);
+ }
+ } catch (NumberFormatException e) {
+ // If something goes wrong in the conversion, it means the number is invalid.
+ return false;
+ }
+ } else if (exclusiveExpressions != null) {
+ // When exclusive expressions are defined, it verifies if the value contains one of the expressions.
+ // If this is the case, it's an invalid value.
+ challenge = Arrays.stream(exclusiveExpressions)
+ .noneMatch(exp -> value.contains(exp));
+ }
+
+ // At the end, it verifies if the value respects the max length. But only if the max length is defined.
+ if (maxLength != null) {
+ challenge &= value.length() <= maxLength;
+ }
+ return challenge;
+ }
+
+ // Each field should implement its own build method.
+ String build() throws MissingParameterException, FieldValidationException {
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdFieldName.java b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdFieldName.java
new file mode 100644
index 0000000..14cbab9
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/CircuitIdFieldName.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent.util;
+
+/**
+ * Represents the field names for circuit-id.
+ */
+public enum CircuitIdFieldName {
+ AcessNodeIdentifier(1),
+ Slot(2),
+ Port(3),
+ OnuSerialNumber(4),
+ UniPortNumber(5),
+ SvID(6),
+ CvID(7),
+ NetworkTechnology(8);
+ private final int value;
+ CircuitIdFieldName(int value) {
+ this.value = value;
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/FieldValidationException.java b/api/src/main/java/org/opencord/pppoeagent/util/FieldValidationException.java
new file mode 100644
index 0000000..8754e74
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/FieldValidationException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent.util;
+
+/**
+ * Exception meant to be thrown when circuit-id builder builds a field which the result
+ * is not valid according to the validation criteria.
+ */
+public class FieldValidationException extends Exception {
+ public FieldValidationException(CircuitIdField field, String value) {
+ super(String.format("Failed to build the circuit ID. %s field is not valid: %s",
+ field.getFieldName().name(), value));
+ }
+
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/MissingParameterException.java b/api/src/main/java/org/opencord/pppoeagent/util/MissingParameterException.java
new file mode 100644
index 0000000..b6f8ec5
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/MissingParameterException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.opencord.pppoeagent.util;
+
+/**
+ * Exception meant to be thrown when circuit-id builder tries to build a
+ * field but there are missing parameterization.
+ */
+public class MissingParameterException extends Exception {
+ public MissingParameterException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/pppoeagent/util/package-info.java b/api/src/main/java/org/opencord/pppoeagent/util/package-info.java
new file mode 100644
index 0000000..6e02984
--- /dev/null
+++ b/api/src/main/java/org/opencord/pppoeagent/util/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * PPPoE agent util api.
+ */
+package org.opencord.pppoeagent.util;