use of org.onlab.packet.PIM in project onos by opennetworkinglab.
the class PimInterface method processHello.
/**
* Process an incoming PIM Hello message. There are a few things going on in
* this method:
* <ul>
* <li>We <em>may</em> have to create a new neighbor if one does not already exist</li>
* <li>We <em>may</em> need to re-elect a new DR if new information is received</li>
* <li>We <em>may</em> need to send an existing neighbor all joins if the genid changed</li>
* <li>We will refresh the neighbor's timestamp</li>
* </ul>
*
* @param ethPkt the Ethernet packet header
*/
public void processHello(Ethernet ethPkt) {
if (log.isTraceEnabled()) {
log.trace("Received a PIM hello packet");
}
// We'll need to save our neighbors MAC address
MacAddress nbrmac = ethPkt.getSourceMAC();
// And we'll need to save neighbors IP Address.
IPv4 iphdr = (IPv4) ethPkt.getPayload();
IpAddress srcip = IpAddress.valueOf(iphdr.getSourceAddress());
PIM pimhdr = (PIM) iphdr.getPayload();
if (pimhdr.getPimMsgType() != PIM.TYPE_HELLO) {
log.error("process Hello has received a non hello packet type: " + pimhdr.getPimMsgType());
return;
}
// get the DR values for later calculation
PimNeighbor dr = pimNeighbors.get(drIpaddress);
checkNotNull(dr);
IpAddress drip = drIpaddress;
int drpri = dr.priority();
// Assume we do not need to run a DR election
boolean reElectDr = false;
boolean genidChanged = false;
PIMHello hello = (PIMHello) pimhdr.getPayload();
// Determine if we already have a PIMNeighbor
PimNeighbor nbr = pimNeighbors.getOrDefault(srcip, null);
PimNeighbor newNbr = PimNeighbor.createPimNeighbor(srcip, nbrmac, hello.getOptions().values());
if (nbr == null) {
pimNeighbors.putIfAbsent(srcip, newNbr);
nbr = newNbr;
} else if (!nbr.equals(newNbr)) {
if (newNbr.holdtime() == 0) {
// Neighbor has shut down. Remove them and clean up
pimNeighbors.remove(srcip, nbr);
return;
} else {
// Neighbor has changed one of their options.
pimNeighbors.put(srcip, newNbr);
nbr = newNbr;
}
}
// Refresh this neighbor's timestamp
nbr.refreshTimestamp();
/*
* the election method will first determine if an election
* needs to be run, if so it will run the election. The
* IP address of the DR will be returned. If the IP address
* of the DR is different from what we already have we know a
* new DR has been elected.
*/
IpAddress electedIp = election(nbr, drip, drpri);
if (!drip.equals(electedIp)) {
// we have a new DR.
drIpaddress = electedIp;
}
}
use of org.onlab.packet.PIM in project onos by opennetworkinglab.
the class PimPacketHandler method processPacket.
/**
* Sanitize and process the packet.
* TODO: replace ConnectPoint with PIMInterface when PIMInterface has been added.
*
* @param ethPkt the packet starting with the Ethernet header.
* @param pimi the PIM Interface the packet arrived on.
*/
public void processPacket(Ethernet ethPkt, PimInterface pimi) {
checkNotNull(ethPkt);
checkNotNull(pimi);
// Sanitize the ethernet header to ensure it is IPv4. IPv6 we'll deal with later
if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
return;
}
// Get the IP header
IPv4 ip = (IPv4) ethPkt.getPayload();
if (ip.getProtocol() != IPv4.PROTOCOL_PIM) {
return;
}
// Get the address of our the neighbor that sent this packet to us.
IpAddress nbraddr = IpAddress.valueOf(ip.getDestinationAddress());
if (log.isTraceEnabled()) {
log.trace("Packet {} received on port {}", nbraddr, pimi);
}
// Get the PIM header
PIM pim = (PIM) ip.getPayload();
checkNotNull(pim);
// Process the pim packet
switch(pim.getPimMsgType()) {
case PIM.TYPE_HELLO:
pimi.processHello(ethPkt);
break;
case PIM.TYPE_JOIN_PRUNE_REQUEST:
pimi.processJoinPrune(ethPkt);
log.debug("Received a PIM Join/Prune message");
break;
default:
log.debug("Received unsupported PIM type: {}", pim.getPimMsgType());
break;
}
}
use of org.onlab.packet.PIM in project onos by opennetworkinglab.
the class PimInterface method processJoinPrune.
/**
* Process an incoming PIM JoinPrune message.
*
* @param ethPkt the Ethernet packet header.
*/
public void processJoinPrune(Ethernet ethPkt) {
IPv4 ip = (IPv4) ethPkt.getPayload();
checkNotNull(ip);
PIM pim = (PIM) ip.getPayload();
checkNotNull(pim);
PIMJoinPrune jpHdr = (PIMJoinPrune) pim.getPayload();
checkNotNull(jpHdr);
/*
* The Join/Prune messages are grouped by Group address. We'll walk each group address
* where we will possibly have to walk a list of source address for the joins and prunes.
*/
Collection<PIMJoinPruneGroup> jpgs = jpHdr.getJoinPrunes();
for (PIMJoinPruneGroup jpg : jpgs) {
IpPrefix gpfx = jpg.getGroup();
// Walk the joins first.
for (IpPrefix spfx : jpg.getJoins().values()) {
// We may need
}
for (IpPrefix spfx : jpg.getPrunes().values()) {
// TODO: this is where we many need to remove multi-cast state and possibly intents.
}
}
}
use of org.onlab.packet.PIM in project onos by opennetworkinglab.
the class PimInterface method sendJoinPrune.
private void sendJoinPrune(McastRoute route, RouteData data, boolean join) {
PIMJoinPrune jp = new PIMJoinPrune();
jp.addJoinPrune(route.source().toIpPrefix(), route.group().toIpPrefix(), join);
jp.setHoldTime(join ? (short) Math.floor(JOIN_PERIOD * HOLD_TIME_MULTIPLIER) : 0);
jp.setUpstreamAddr(new PIMAddrUnicast(data.ipAddress.toString()));
PIM pim = new PIM();
pim.setPIMType(PIM.TYPE_JOIN_PRUNE_REQUEST);
pim.setPayload(jp);
IPv4 ipv4 = new IPv4();
ipv4.setDestinationAddress(PIM.PIM_ADDRESS.getIp4Address().toInt());
ipv4.setSourceAddress(getIpAddress().getIp4Address().toInt());
ipv4.setProtocol(IPv4.PROTOCOL_PIM);
ipv4.setTtl((byte) 1);
ipv4.setDiffServ((byte) 0xc0);
ipv4.setPayload(pim);
Ethernet eth = new Ethernet();
eth.setSourceMACAddress(onosInterface.mac());
eth.setDestinationMACAddress(MacAddress.valueOf("01:00:5E:00:00:0d"));
eth.setEtherType(Ethernet.TYPE_IPV4);
eth.setPayload(ipv4);
TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(onosInterface.connectPoint().port()).build();
packetService.emit(new DefaultOutboundPacket(onosInterface.connectPoint().deviceId(), treatment, ByteBuffer.wrap(eth.serialize())));
data.timestamp = System.currentTimeMillis();
}
Aggregations