Jonathan Hart

Clean up a few SSM-translate things, incl config validation

Change-Id: I5308fd8a73088ea6a522f22642ee834ac8a7a446
......@@ -84,7 +84,6 @@ import static org.slf4j.LoggerFactory.getLogger;
@Component(immediate = true)
public class IgmpSnoop {
private final Logger log = getLogger(getClass());
private static final String DEST_MAC = "01:00:5E:00:00:01";
......@@ -144,6 +143,9 @@ public class IgmpSnoop {
private static final Class<AccessDeviceConfig> CONFIG_CLASS =
AccessDeviceConfig.class;
private static final Class<IgmpSsmTranslateConfig> SSM_TRANSLATE_CONFIG_CLASS =
IgmpSsmTranslateConfig.class;
private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
new ConfigFactory<DeviceId, AccessDeviceConfig>(
SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
......@@ -155,7 +157,7 @@ public class IgmpSnoop {
private ConfigFactory<ApplicationId, IgmpSsmTranslateConfig> ssmTranslateConfigFactory =
new ConfigFactory<ApplicationId, IgmpSsmTranslateConfig>(
SubjectFactories.APP_SUBJECT_FACTORY, IgmpSsmTranslateConfig.class, "ssmTranslate", true) {
SubjectFactories.APP_SUBJECT_FACTORY, SSM_TRANSLATE_CONFIG_CLASS, "ssmTranslate", true) {
@Override
public IgmpSsmTranslateConfig createConfig() {
return new IgmpSsmTranslateConfig();
......@@ -466,9 +468,25 @@ public class IgmpSnoop {
provisionDefaultFlows((DeviceId) event.subject());
}
}
if (event.configClass().equals(SSM_TRANSLATE_CONFIG_CLASS)) {
IgmpSsmTranslateConfig config =
networkConfig.getConfig((ApplicationId) event.subject(),
SSM_TRANSLATE_CONFIG_CLASS);
if (config != null) {
ssmTranslateTable.clear();
config.getSsmTranslations().forEach(
route -> ssmTranslateTable.put(route.group(), route.source()));
}
}
break;
case CONFIG_REGISTERED:
case CONFIG_UNREGISTERED:
break;
case CONFIG_REMOVED:
if (event.configClass().equals(SSM_TRANSLATE_CONFIG_CLASS)) {
ssmTranslateTable.clear();
}
default:
break;
}
......
......@@ -17,6 +17,7 @@
package org.onosproject.igmp;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.packet.IpAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
......@@ -26,13 +27,34 @@ import java.util.ArrayList;
import java.util.List;
/**
* Created by jono on 2/16/16.
* IGMP SSM translate configuration.
*/
public class IgmpSsmTranslateConfig extends Config<ApplicationId> {
private static final String SSM_TRANSLATE = "ssmTranslate";
private static final String SOURCE = "source";
private static final String GROUP = "group";
@Override
public boolean isValid() {
for (JsonNode node : array) {
if (!hasOnlyFields((ObjectNode) node, SOURCE, GROUP)) {
return false;
}
if (!(isIpAddress((ObjectNode) node, SOURCE, FieldPresence.MANDATORY) &&
isIpAddress((ObjectNode) node, GROUP, FieldPresence.MANDATORY))) {
return false;
}
}
return true;
}
/**
* Gets the list of SSM translations.
*
* @return SSM translations
*/
public List<McastRoute> getSsmTranslations() {
List<McastRoute> translations = new ArrayList();
for (JsonNode node : array) {
......
......@@ -393,8 +393,20 @@ public abstract class Config<S> {
* @return true if all allowedFields are present; false otherwise
*/
protected boolean hasOnlyFields(String... allowedFields) {
return hasOnlyFields(object, allowedFields);
}
/**
* Indicates whether only the specified fields are present in a particular
* JSON object.
*
* @param node node whose fields to check
* @param allowedFields allowed field names
* @return true if all allowedFields are present; false otherwise
*/
protected boolean hasOnlyFields(ObjectNode node, String... allowedFields) {
Set<String> fields = ImmutableSet.copyOf(allowedFields);
return !Iterators.any(object.fieldNames(), f -> !fields.contains(f));
return !Iterators.any(node.fieldNames(), f -> !fields.contains(f));
}
/**
......@@ -420,9 +432,23 @@ public abstract class Config<S> {
* @throws IllegalArgumentException if field is present, but not valid IP
*/
protected boolean isIpAddress(String field, FieldPresence presence) {
JsonNode node = object.path(field);
return isValid(node, presence, node.isTextual() &&
IpAddress.valueOf(node.asText()) != null);
return isIpAddress(object, field, presence);
}
/**
* Indicates whether the specified field of a particular node holds a valid
* IP address.
*
* @param node node from whom to access the field
* @param field JSON field name
* @param presence specifies if field is optional or mandatory
* @return true if valid; false otherwise
* @throws IllegalArgumentException if field is present, but not valid IP
*/
protected boolean isIpAddress(ObjectNode node, String field, FieldPresence presence) {
JsonNode innerNode = node.path(field);
return isValid(innerNode, presence, innerNode.isTextual() &&
IpAddress.valueOf(innerNode.asText()) != null);
}
/**
......