Clean up a few SSM-translate things, incl config validation
Change-Id: I5308fd8a73088ea6a522f22642ee834ac8a7a446
Showing
3 changed files
with
74 additions
and
8 deletions
| ... | @@ -84,7 +84,6 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -84,7 +84,6 @@ import static org.slf4j.LoggerFactory.getLogger; |
| 84 | @Component(immediate = true) | 84 | @Component(immediate = true) |
| 85 | public class IgmpSnoop { | 85 | public class IgmpSnoop { |
| 86 | 86 | ||
| 87 | - | ||
| 88 | private final Logger log = getLogger(getClass()); | 87 | private final Logger log = getLogger(getClass()); |
| 89 | 88 | ||
| 90 | private static final String DEST_MAC = "01:00:5E:00:00:01"; | 89 | private static final String DEST_MAC = "01:00:5E:00:00:01"; |
| ... | @@ -144,6 +143,9 @@ public class IgmpSnoop { | ... | @@ -144,6 +143,9 @@ public class IgmpSnoop { |
| 144 | private static final Class<AccessDeviceConfig> CONFIG_CLASS = | 143 | private static final Class<AccessDeviceConfig> CONFIG_CLASS = |
| 145 | AccessDeviceConfig.class; | 144 | AccessDeviceConfig.class; |
| 146 | 145 | ||
| 146 | + private static final Class<IgmpSsmTranslateConfig> SSM_TRANSLATE_CONFIG_CLASS = | ||
| 147 | + IgmpSsmTranslateConfig.class; | ||
| 148 | + | ||
| 147 | private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory = | 149 | private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory = |
| 148 | new ConfigFactory<DeviceId, AccessDeviceConfig>( | 150 | new ConfigFactory<DeviceId, AccessDeviceConfig>( |
| 149 | SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") { | 151 | SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") { |
| ... | @@ -155,7 +157,7 @@ public class IgmpSnoop { | ... | @@ -155,7 +157,7 @@ public class IgmpSnoop { |
| 155 | 157 | ||
| 156 | private ConfigFactory<ApplicationId, IgmpSsmTranslateConfig> ssmTranslateConfigFactory = | 158 | private ConfigFactory<ApplicationId, IgmpSsmTranslateConfig> ssmTranslateConfigFactory = |
| 157 | new ConfigFactory<ApplicationId, IgmpSsmTranslateConfig>( | 159 | new ConfigFactory<ApplicationId, IgmpSsmTranslateConfig>( |
| 158 | - SubjectFactories.APP_SUBJECT_FACTORY, IgmpSsmTranslateConfig.class, "ssmTranslate", true) { | 160 | + SubjectFactories.APP_SUBJECT_FACTORY, SSM_TRANSLATE_CONFIG_CLASS, "ssmTranslate", true) { |
| 159 | @Override | 161 | @Override |
| 160 | public IgmpSsmTranslateConfig createConfig() { | 162 | public IgmpSsmTranslateConfig createConfig() { |
| 161 | return new IgmpSsmTranslateConfig(); | 163 | return new IgmpSsmTranslateConfig(); |
| ... | @@ -466,9 +468,25 @@ public class IgmpSnoop { | ... | @@ -466,9 +468,25 @@ public class IgmpSnoop { |
| 466 | provisionDefaultFlows((DeviceId) event.subject()); | 468 | provisionDefaultFlows((DeviceId) event.subject()); |
| 467 | } | 469 | } |
| 468 | } | 470 | } |
| 471 | + if (event.configClass().equals(SSM_TRANSLATE_CONFIG_CLASS)) { | ||
| 472 | + IgmpSsmTranslateConfig config = | ||
| 473 | + networkConfig.getConfig((ApplicationId) event.subject(), | ||
| 474 | + SSM_TRANSLATE_CONFIG_CLASS); | ||
| 475 | + | ||
| 476 | + if (config != null) { | ||
| 477 | + ssmTranslateTable.clear(); | ||
| 478 | + config.getSsmTranslations().forEach( | ||
| 479 | + route -> ssmTranslateTable.put(route.group(), route.source())); | ||
| 480 | + } | ||
| 481 | + } | ||
| 469 | break; | 482 | break; |
| 483 | + case CONFIG_REGISTERED: | ||
| 470 | case CONFIG_UNREGISTERED: | 484 | case CONFIG_UNREGISTERED: |
| 485 | + break; | ||
| 471 | case CONFIG_REMOVED: | 486 | case CONFIG_REMOVED: |
| 487 | + if (event.configClass().equals(SSM_TRANSLATE_CONFIG_CLASS)) { | ||
| 488 | + ssmTranslateTable.clear(); | ||
| 489 | + } | ||
| 472 | default: | 490 | default: |
| 473 | break; | 491 | break; |
| 474 | } | 492 | } | ... | ... |
| ... | @@ -17,6 +17,7 @@ | ... | @@ -17,6 +17,7 @@ |
| 17 | package org.onosproject.igmp; | 17 | package org.onosproject.igmp; |
| 18 | 18 | ||
| 19 | import com.fasterxml.jackson.databind.JsonNode; | 19 | import com.fasterxml.jackson.databind.JsonNode; |
| 20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | import org.onlab.packet.IpAddress; | 21 | import org.onlab.packet.IpAddress; |
| 21 | import org.onosproject.core.ApplicationId; | 22 | import org.onosproject.core.ApplicationId; |
| 22 | import org.onosproject.net.config.Config; | 23 | import org.onosproject.net.config.Config; |
| ... | @@ -26,13 +27,34 @@ import java.util.ArrayList; | ... | @@ -26,13 +27,34 @@ import java.util.ArrayList; |
| 26 | import java.util.List; | 27 | import java.util.List; |
| 27 | 28 | ||
| 28 | /** | 29 | /** |
| 29 | - * Created by jono on 2/16/16. | 30 | + * IGMP SSM translate configuration. |
| 30 | */ | 31 | */ |
| 31 | public class IgmpSsmTranslateConfig extends Config<ApplicationId> { | 32 | public class IgmpSsmTranslateConfig extends Config<ApplicationId> { |
| 32 | - private static final String SSM_TRANSLATE = "ssmTranslate"; | 33 | + |
| 33 | private static final String SOURCE = "source"; | 34 | private static final String SOURCE = "source"; |
| 34 | private static final String GROUP = "group"; | 35 | private static final String GROUP = "group"; |
| 35 | 36 | ||
| 37 | + @Override | ||
| 38 | + public boolean isValid() { | ||
| 39 | + for (JsonNode node : array) { | ||
| 40 | + if (!hasOnlyFields((ObjectNode) node, SOURCE, GROUP)) { | ||
| 41 | + return false; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + if (!(isIpAddress((ObjectNode) node, SOURCE, FieldPresence.MANDATORY) && | ||
| 45 | + isIpAddress((ObjectNode) node, GROUP, FieldPresence.MANDATORY))) { | ||
| 46 | + return false; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + } | ||
| 50 | + return true; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * Gets the list of SSM translations. | ||
| 55 | + * | ||
| 56 | + * @return SSM translations | ||
| 57 | + */ | ||
| 36 | public List<McastRoute> getSsmTranslations() { | 58 | public List<McastRoute> getSsmTranslations() { |
| 37 | List<McastRoute> translations = new ArrayList(); | 59 | List<McastRoute> translations = new ArrayList(); |
| 38 | for (JsonNode node : array) { | 60 | for (JsonNode node : array) { | ... | ... |
| ... | @@ -393,8 +393,20 @@ public abstract class Config<S> { | ... | @@ -393,8 +393,20 @@ public abstract class Config<S> { |
| 393 | * @return true if all allowedFields are present; false otherwise | 393 | * @return true if all allowedFields are present; false otherwise |
| 394 | */ | 394 | */ |
| 395 | protected boolean hasOnlyFields(String... allowedFields) { | 395 | protected boolean hasOnlyFields(String... allowedFields) { |
| 396 | + return hasOnlyFields(object, allowedFields); | ||
| 397 | + } | ||
| 398 | + | ||
| 399 | + /** | ||
| 400 | + * Indicates whether only the specified fields are present in a particular | ||
| 401 | + * JSON object. | ||
| 402 | + * | ||
| 403 | + * @param node node whose fields to check | ||
| 404 | + * @param allowedFields allowed field names | ||
| 405 | + * @return true if all allowedFields are present; false otherwise | ||
| 406 | + */ | ||
| 407 | + protected boolean hasOnlyFields(ObjectNode node, String... allowedFields) { | ||
| 396 | Set<String> fields = ImmutableSet.copyOf(allowedFields); | 408 | Set<String> fields = ImmutableSet.copyOf(allowedFields); |
| 397 | - return !Iterators.any(object.fieldNames(), f -> !fields.contains(f)); | 409 | + return !Iterators.any(node.fieldNames(), f -> !fields.contains(f)); |
| 398 | } | 410 | } |
| 399 | 411 | ||
| 400 | /** | 412 | /** |
| ... | @@ -420,9 +432,23 @@ public abstract class Config<S> { | ... | @@ -420,9 +432,23 @@ public abstract class Config<S> { |
| 420 | * @throws IllegalArgumentException if field is present, but not valid IP | 432 | * @throws IllegalArgumentException if field is present, but not valid IP |
| 421 | */ | 433 | */ |
| 422 | protected boolean isIpAddress(String field, FieldPresence presence) { | 434 | protected boolean isIpAddress(String field, FieldPresence presence) { |
| 423 | - JsonNode node = object.path(field); | 435 | + return isIpAddress(object, field, presence); |
| 424 | - return isValid(node, presence, node.isTextual() && | 436 | + } |
| 425 | - IpAddress.valueOf(node.asText()) != null); | 437 | + |
| 438 | + /** | ||
| 439 | + * Indicates whether the specified field of a particular node holds a valid | ||
| 440 | + * IP address. | ||
| 441 | + * | ||
| 442 | + * @param node node from whom to access the field | ||
| 443 | + * @param field JSON field name | ||
| 444 | + * @param presence specifies if field is optional or mandatory | ||
| 445 | + * @return true if valid; false otherwise | ||
| 446 | + * @throws IllegalArgumentException if field is present, but not valid IP | ||
| 447 | + */ | ||
| 448 | + protected boolean isIpAddress(ObjectNode node, String field, FieldPresence presence) { | ||
| 449 | + JsonNode innerNode = node.path(field); | ||
| 450 | + return isValid(innerNode, presence, innerNode.isTextual() && | ||
| 451 | + IpAddress.valueOf(innerNode.asText()) != null); | ||
| 426 | } | 452 | } |
| 427 | 453 | ||
| 428 | /** | 454 | /** | ... | ... |
-
Please register or login to post a comment