[SEBA-40, SEBA-942 & SEBA-957] Operational status for IGMP Channel, IGMP Group and Invalid IGMP Packets
Change-Id: I8efb475f69ca5df8f2f4c1daaaba52b8ce8572f7
diff --git a/src/main/java/org/opencord/igmpproxy/IgmpManager.java b/src/main/java/org/opencord/igmpproxy/IgmpManager.java
index a42d41b..d5677f0 100644
--- a/src/main/java/org/opencord/igmpproxy/IgmpManager.java
+++ b/src/main/java/org/opencord/igmpproxy/IgmpManager.java
@@ -72,6 +72,8 @@
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
@@ -85,6 +87,13 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import static org.onlab.packet.IGMPMembership.MODE_IS_INCLUDE;
+import static org.onlab.packet.IGMPMembership.MODE_IS_EXCLUDE;
+import static org.onlab.packet.IGMPMembership.CHANGE_TO_INCLUDE_MODE;
+import static org.onlab.packet.IGMPMembership.CHANGE_TO_EXCLUDE_MODE;
+import static org.onlab.packet.IGMPMembership.ALLOW_NEW_SOURCES;
+import static org.onlab.packet.IGMPMembership.BLOCK_OLD_SOURCES;
+
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
@@ -202,12 +211,15 @@
protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
+ private List<Byte> validMembershipModes = Arrays.asList(MODE_IS_INCLUDE, MODE_IS_EXCLUDE, CHANGE_TO_INCLUDE_MODE,
+ CHANGE_TO_EXCLUDE_MODE, ALLOW_NEW_SOURCES, BLOCK_OLD_SOURCES);
+
@Activate
protected void activate() {
appId = coreService.registerApplication(APP_NAME);
coreAppId = coreService.registerApplication(CoreService.CORE_APP_NAME);
packetService.addProcessor(processor, PacketProcessor.director(4));
- IgmpSender.init(packetService, mastershipService);
+ IgmpSender.init(packetService, mastershipService, igmpStatisticsManager);
networkConfig.registerConfigFactory(igmpproxySsmConfigFactory);
networkConfig.registerConfigFactory(igmpproxyConfigFactory);
@@ -268,8 +280,10 @@
maxResp = calculateMaxResp(maxResp);
if (gAddr != null && !gAddr.isZero()) {
StateMachine.specialQuery(deviceId, gAddr, maxResp);
+ igmpStatisticsManager.getIgmpStats().increaseIgmpGrpSpecificMembershipQuery();
} else {
StateMachine.generalQuery(deviceId, maxResp);
+ igmpStatisticsManager.getIgmpStats().increaseIgmpGeneralMembershipQuery();
}
}
@@ -284,12 +298,15 @@
Optional<SubscriberAndDeviceInformation> accessDevice = getSubscriberAndDeviceInformation(device.id());
if (accessDevice.isPresent()) {
StateMachine.specialQuery(device.id(), gAddr, maxResponseTime);
+ igmpStatisticsManager.getIgmpStats().increaseIgmpGrpAndSrcSpecificMembershipQuery();
}
});
+ igmpStatisticsManager.getIgmpStats().increaseCurrentGrpNumCounter();
} else {
//Don't know which group is targeted by the query
//So query all the members(in all the OLTs) and proxy their reports
StateMachine.generalQuery(maxResponseTime);
+ igmpStatisticsManager.getIgmpStats().increaseIgmpGeneralMembershipQuery();
}
}
@@ -315,6 +332,7 @@
Ip4Address groupIp = igmpGroup.getGaddr().getIp4Address();
if (!groupIp.isMulticast()) {
log.info(groupIp.toString() + " is not a valid group address");
+ igmpStatisticsManager.getIgmpStats().increaseFailJoinReqUnknownMulticastIpCounter();
return;
}
Ip4Address srcIp = getDeviceIp(deviceId);
@@ -324,6 +342,9 @@
ArrayList<Ip4Address> sourceList = new ArrayList<>();
+ if (!validMembershipModes.contains(recordType)) {
+ igmpStatisticsManager.getIgmpStats().increaseReportsRxWithWrongModeCounter();
+ }
if (igmpGroup.getSources().size() > 0) {
igmpGroup.getSources().forEach(source -> sourceList.add(source.getIp4Address()));
if (recordType == IGMPMembership.CHANGE_TO_EXCLUDE_MODE ||
@@ -368,6 +389,7 @@
igmpStatisticsManager.getIgmpStats().increaseIgmpFailJoinReq();
log.warn("Unable to process IGMP Join from {} since no source " +
"configuration is found.", deviceId);
+ igmpStatisticsManager.getIgmpStats().increaseFailJoinReqInsuffPermissionAccessCounter();
return;
}
@@ -389,6 +411,7 @@
boolean isJoined = StateMachine.join(deviceId, groupIp, srcIp, deviceUplink.get());
if (isJoined) {
igmpStatisticsManager.getIgmpStats().increaseIgmpSuccessJoinRejoinReq();
+ igmpStatisticsManager.getIgmpStats().increaseIgmpChannelJoinCounter();
} else {
igmpStatisticsManager.getIgmpStats().increaseIgmpFailJoinReq();
}
@@ -403,6 +426,7 @@
//add sink to the route
multicastService.addSinks(route, Sets.newHashSet(cp));
});
+ igmpStatisticsManager.getIgmpStats().increaseUnconfiguredGroupCounter();
}
groupMember.resetAllTimers();
@@ -413,6 +437,7 @@
if (groupMember == null) {
log.info("receive leave but no instance, group " + groupIp.toString() +
" device:" + deviceId.toString() + " port:" + portNumber.toString());
+ igmpStatisticsManager.getIgmpStats().increaseUnconfiguredGroupCounter();
return;
} else {
groupMember.setLeave(true);
@@ -480,12 +505,14 @@
return;
}
+ igmpStatisticsManager.getIgmpStats().increaseIgmpValidChecksumCounter();
short vlan = ethPkt.getVlanID();
DeviceId deviceId = pkt.receivedFrom().deviceId();
if (!isConnectPoint(deviceId, pkt.receivedFrom().port()) &&
!getSubscriberAndDeviceInformation(deviceId).isPresent()) {
log.error("Device not registered in netcfg :" + deviceId.toString());
+ igmpStatisticsManager.getIgmpStats().increaseFailJoinReqInsuffPermissionAccessCounter();
return;
}
@@ -535,6 +562,7 @@
default:
log.warn("wrong IGMP v3 type:" + igmp.getIgmpType());
igmpStatisticsManager.getIgmpStats().increaseInvalidIgmpMsgReceived();
+ igmpStatisticsManager.getIgmpStats().increaseUnknownIgmpTypePacketsRxCounter();
break;
}
diff --git a/src/main/java/org/opencord/igmpproxy/IgmpSender.java b/src/main/java/org/opencord/igmpproxy/IgmpSender.java
index b455cb4..02cc4ee 100644
--- a/src/main/java/org/opencord/igmpproxy/IgmpSender.java
+++ b/src/main/java/org/opencord/igmpproxy/IgmpSender.java
@@ -17,6 +17,8 @@
import org.onlab.packet.Ethernet;
import org.onlab.packet.IGMP;
+import org.onlab.packet.IGMP.IGMPv2;
+import org.onlab.packet.IGMP.IGMPv3;
import org.onlab.packet.IGMPMembership;
import org.onlab.packet.IGMPQuery;
import org.onlab.packet.IPv4;
@@ -49,6 +51,7 @@
private static IgmpSender instance = null;
private PacketService packetService;
private MastershipService mastershipService;
+ private IgmpStatisticsService igmpStatisticsService;
private boolean withRAUplink = true;
private boolean withRADownlink = false;
private short mvlan = DEFAULT_MVLAN;
@@ -56,13 +59,16 @@
private int maxResp = DEFAULT_MEX_RESP;
private Logger log = LoggerFactory.getLogger(getClass());
- private IgmpSender(PacketService packetService, MastershipService mastershipService) {
+ private IgmpSender(PacketService packetService, MastershipService mastershipService,
+ IgmpStatisticsService igmpStatisticsService) {
this.packetService = packetService;
this.mastershipService = mastershipService;
+ this.igmpStatisticsService = igmpStatisticsService;
}
- public static void init(PacketService packetService, MastershipService mastershipService) {
- instance = new IgmpSender(packetService, mastershipService);
+ public static void init(PacketService packetService, MastershipService mastershipService,
+ IgmpStatisticsService igmpStatisticsService) {
+ instance = new IgmpSender(packetService, mastershipService, igmpStatisticsService);
}
public static IgmpSender getInstance() {
@@ -118,7 +124,7 @@
return buildIgmpPacket(IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY, groupIp, null, sourceIp, false);
}
- private Ethernet buildIgmpPacket(byte type, Ip4Address groupIp, IGMPMembership igmpMembership,
+ protected Ethernet buildIgmpPacket(byte type, Ip4Address groupIp, IGMPMembership igmpMembership,
Ip4Address sourceIp, boolean isV2Query) {
IGMP igmpPacket;
@@ -164,6 +170,7 @@
case IGMP.TYPE_IGMPV2_LEAVE_GROUP:
return null;
default:
+ igmpStatisticsService.getIgmpStats().increaseUnknownIgmpTypePacketsRxCounter();
return null;
}
@@ -216,10 +223,23 @@
return;
}
+ IPv4 ipv4Pkt = (IPv4) ethPkt.getPayload();
+ IGMP igmp = (IGMP) ipv4Pkt.getPayload();
+ // We are checking the length of packets. Right now the counter value will be 0 because of internal translation
+ // As packet length will always be valid
+ // This counter will be useful in future if we change the procedure to generate the packets.
+ if ((igmp.getIgmpType() == IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT
+ || igmp.getIgmpType() == IGMP.TYPE_IGMPV2_LEAVE_GROUP) && igmp.serialize().length < IGMPv2.HEADER_LENGTH) {
+ igmpStatisticsService.getIgmpStats().increaseInvalidIgmpLength();
+ } else if (igmp.getIgmpType() == IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT
+ && igmp.serialize().length < IGMPv3.MINIMUM_HEADER_LEN) {
+ igmpStatisticsService.getIgmpStats().increaseInvalidIgmpLength();
+ }
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(portNumber).build();
OutboundPacket packet = new DefaultOutboundPacket(deviceId,
treatment, ByteBuffer.wrap(ethPkt.serialize()));
+ igmpStatisticsService.getIgmpStats().increaseValidIgmpPacketCounter();
packetService.emit(packet);
}
diff --git a/src/main/java/org/opencord/igmpproxy/IgmpStatistics.java b/src/main/java/org/opencord/igmpproxy/IgmpStatistics.java
index c7c4650..f330e9f 100644
--- a/src/main/java/org/opencord/igmpproxy/IgmpStatistics.java
+++ b/src/main/java/org/opencord/igmpproxy/IgmpStatistics.java
@@ -50,6 +50,32 @@
private AtomicLong igmpMsgReceived = new AtomicLong();
//Total number of invalid IGMP messages received
private AtomicLong invalidIgmpMsgReceived = new AtomicLong();
+ //Counter for unknown igmp type
+ private AtomicLong unknownIgmpTypePacketsRxCounter = new AtomicLong();
+ // Counter for igmp report with wrong mode.
+ private AtomicLong reportsRxWithWrongModeCounter = new AtomicLong();
+ // Counter for failed join due to insufficient permission access
+ private AtomicLong failJoinReqInsuffPermissionAccessCounter = new AtomicLong();
+ // Counter for invalid group ip address i.e not a valid multicast address.
+ private AtomicLong failJoinReqUnknownMulticastIpCounter = new AtomicLong();
+ // Counter for unconfigured group
+ private AtomicLong unconfiguredGroupCounter = new AtomicLong();
+ // Counter for valid igmp packet
+ private AtomicLong validIgmpPacketCounter = new AtomicLong();
+ // Counter for current number of igmp channel joins
+ private AtomicLong igmpChannelJoinCounter = new AtomicLong();
+ // Counter for current group number
+ private AtomicLong currentGrpNumCounter = new AtomicLong();
+ // Counter for igmp Checksum
+ private AtomicLong igmpValidChecksumCounter = new AtomicLong();
+ // Counter for Invalid Igmp Length
+ private AtomicLong invalidIgmpLength = new AtomicLong();
+ //Total number of general IGMP membership query messages received
+ private AtomicLong igmpGeneralMembershipQuery = new AtomicLong();
+ //Total number of group specific IGMP membership query messages received
+ private AtomicLong igmpGrpSpecificMembershipQuery = new AtomicLong();
+ //Total number of group and source specific IGMP membership query messages received
+ private AtomicLong igmpGrpAndSrcSpecificMembershipQuery = new AtomicLong();
public Long getIgmpJoinReq() {
return igmpJoinReq.get();
@@ -156,4 +182,107 @@
totalMsgReceived.incrementAndGet();
}
+ public Long getValidIgmpPacketCounter() {
+ return validIgmpPacketCounter.get();
+ }
+
+ public void increaseValidIgmpPacketCounter() {
+ validIgmpPacketCounter.incrementAndGet();
+ }
+
+ public Long getCurrentGrpNumCounter() {
+ return currentGrpNumCounter.get();
+ }
+
+ public void increaseCurrentGrpNumCounter() {
+ currentGrpNumCounter.incrementAndGet();
+ }
+
+ public Long getIgmpChannelJoinCounter() {
+ return igmpChannelJoinCounter.get();
+ }
+ public Long getIgmpValidChecksumCounter() {
+ return igmpValidChecksumCounter.get();
+ }
+
+ public void increaseIgmpChannelJoinCounter() {
+ igmpChannelJoinCounter.incrementAndGet();
+ }
+
+ public void increaseIgmpValidChecksumCounter() {
+ igmpValidChecksumCounter.incrementAndGet();
+ }
+
+ public Long getUnconfiguredGroupCounter() {
+ return unconfiguredGroupCounter.get();
+ }
+
+ public void increaseUnconfiguredGroupCounter() {
+ unconfiguredGroupCounter.incrementAndGet();
+ }
+
+ public Long getFailJoinReqUnknownMulticastIpCounter() {
+ return failJoinReqUnknownMulticastIpCounter.get();
+ }
+
+ public void increaseFailJoinReqUnknownMulticastIpCounter() {
+ failJoinReqUnknownMulticastIpCounter.incrementAndGet();
+ }
+
+ public Long getFailJoinReqInsuffPermissionAccessCounter() {
+ return failJoinReqInsuffPermissionAccessCounter.get();
+ }
+
+ public void increaseFailJoinReqInsuffPermissionAccessCounter() {
+ failJoinReqInsuffPermissionAccessCounter.incrementAndGet();
+ }
+
+ public Long getReportsRxWithWrongModeCounter() {
+ return reportsRxWithWrongModeCounter.get();
+ }
+
+ public Long getUnknownIgmpTypePacketsRxCounter() {
+ return unknownIgmpTypePacketsRxCounter.get();
+ }
+
+ public void increaseUnknownIgmpTypePacketsRxCounter() {
+ unknownIgmpTypePacketsRxCounter.incrementAndGet();
+ }
+
+ public void increaseReportsRxWithWrongModeCounter() {
+ reportsRxWithWrongModeCounter.incrementAndGet();
+ }
+
+ public Long getInvalidIgmpLength() {
+ return invalidIgmpLength.get();
+ }
+
+ public void increaseInvalidIgmpLength() {
+ invalidIgmpLength.incrementAndGet();
+ }
+
+ public Long getIgmpGeneralMembershipQuery() {
+ return igmpGeneralMembershipQuery.get();
+ }
+
+ public Long getIgmpGrpSpecificMembershipQuery() {
+ return igmpGrpSpecificMembershipQuery.get();
+ }
+
+ public Long getIgmpGrpAndSrcSpecificMembershipQuery() {
+ return igmpGrpAndSrcSpecificMembershipQuery.get();
+ }
+
+ public void increaseIgmpGeneralMembershipQuery() {
+ igmpGeneralMembershipQuery.incrementAndGet();
+ }
+
+ public void increaseIgmpGrpSpecificMembershipQuery() {
+ igmpGrpSpecificMembershipQuery.incrementAndGet();
+ }
+
+ public void increaseIgmpGrpAndSrcSpecificMembershipQuery() {
+ igmpGrpAndSrcSpecificMembershipQuery.incrementAndGet();
+ }
+
}
diff --git a/src/main/java/org/opencord/igmpproxy/IgmpStatisticsManager.java b/src/main/java/org/opencord/igmpproxy/IgmpStatisticsManager.java
index a30c5e8..af834ef 100644
--- a/src/main/java/org/opencord/igmpproxy/IgmpStatisticsManager.java
+++ b/src/main/java/org/opencord/igmpproxy/IgmpStatisticsManager.java
@@ -132,6 +132,19 @@
log.debug("--Igmpv3MembershipReport--" + igmpStats.getIgmpv3MembershipReport());
log.debug("--InvalidIgmpMsgReceived--" + igmpStats.getInvalidIgmpMsgReceived());
log.debug("--TotalMsgReceived-- " + igmpStats.getTotalMsgReceived());
+ log.debug("--UnknownIgmpTypePacketsRx--" + igmpStats.getUnknownIgmpTypePacketsRxCounter());
+ log.debug("--ReportsRxWithWrongMode--" + igmpStats.getReportsRxWithWrongModeCounter());
+ log.debug("--FailJoinReqInsuffPermission--" + igmpStats.getFailJoinReqInsuffPermissionAccessCounter());
+ log.debug("--FailJoinReqUnknownMulticastIp--" + igmpStats.getFailJoinReqUnknownMulticastIpCounter());
+ log.debug("--UnconfiguredGroupCounter--" + igmpStats.getUnconfiguredGroupCounter());
+ log.debug("--ValidIgmpPacketCounter--" + igmpStats.getValidIgmpPacketCounter());
+ log.debug("--IgmpChannelJoinCounter--" + igmpStats.getIgmpChannelJoinCounter());
+ log.debug("--CurrentGrpNumCounter--" + igmpStats.getCurrentGrpNumCounter());
+ log.debug("--IgmpValidChecksumCounter--" + igmpStats.getIgmpValidChecksumCounter());
+ log.debug("--InvalidIgmpLength--" + igmpStats.getInvalidIgmpLength());
+ log.debug("--IgmpGeneralMembershipQuery--" + igmpStats.getIgmpGeneralMembershipQuery());
+ log.debug("--IgmpGrpSpecificMembershipQuery--" + igmpStats.getIgmpGrpSpecificMembershipQuery());
+ log.debug("--IgmpGrpAndSrcSpecificMembershipQuery--" + igmpStats.getIgmpGrpAndSrcSpecificMembershipQuery());
}
post(new IgmpStatisticsEvent(IgmpStatisticsEvent.Type.STATS_UPDATE, igmpStats));