package org.freertr.serv; import java.util.ArrayList; import java.util.List; import org.freertr.addr.addrIP; import org.freertr.cfg.cfgAll; import org.freertr.cfg.cfgVrf; import org.freertr.ip.ipFwd; import org.freertr.pack.packPcep; import org.freertr.pipe.pipeLine; import org.freertr.pipe.pipeSide; import org.freertr.prt.prtGenConn; import org.freertr.prt.prtServS; import org.freertr.tab.tabGen; import org.freertr.tab.tabHop; import org.freertr.tab.tabRouteEntry; import org.freertr.user.userFilter; import org.freertr.user.userHelping; import org.freertr.util.bits; import org.freertr.util.cmds; import org.freertr.util.debugger; import org.freertr.util.logger; /** * path computation element protocol (rfc5440) server * * @author matecsaba */ public class servPcep extends servGeneric implements prtServS { /** * create instance */ public servPcep() { } /** * logging */ public boolean logging; /** * explicit */ public boolean explicit; /** * exported vrf */ public cfgVrf expVrf; /** * defaults text */ public final static String[] defaultL = { "server pcep .*!" + cmds.tabulator + "port " + packPcep.port, "server pcep .*!" + cmds.tabulator + "protocol " + proto2string(protoAllStrm), "server pcep .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "explicit", "server pcep .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "logging" }; /** * defaults filter */ public static tabGen defaultF; public tabGen srvDefFlt() { return defaultF; } public String srvName() { return "pcep"; } public int srvPort() { return packPcep.port; } public int srvProto() { return protoAllStrm; } public boolean srvInit() { return genStrmStart(this, new pipeLine(32768, false), 0); } public boolean srvDeinit() { return genericStop(0); } public void srvShRun(String beg, List l, int filter) { cmds.cfgLine(l, !logging, beg, "logging", ""); cmds.cfgLine(l, !explicit, beg, "explicit", ""); if (expVrf == null) { l.add(beg + "no export-vrf"); } else { l.add(beg + "export-vrf " + expVrf.name); } } public boolean srvCfgStr(cmds cmd) { String s = cmd.word(); if (s.equals("export-vrf")) { expVrf = cfgAll.vrfFind(cmd.word(), false); if (expVrf == null) { cmd.error("no such vrf"); } return false; } if (s.equals("logging")) { logging = true; return false; } if (s.equals("explicit")) { explicit = true; return false; } if (!s.equals(cmds.negated)) { return true; } s = cmd.word(); if (s.equals("export-vrf")) { expVrf = null; return false; } if (s.equals("logging")) { logging = false; return false; } if (s.equals("explicit")) { explicit = false; return false; } return true; } public void srvHelp(userHelping l) { l.add(null, "1 . logging log user communication"); l.add(null, "1 . explicit respond with explicit labels"); l.add(null, "1 2 export-vrf specify vrf to export"); l.add(null, "2 . vrf name"); } public boolean srvAccept(pipeSide pipe, prtGenConn id) { pipe.setTime(120000); pipe.lineRx = pipeSide.modTyp.modeCR; pipe.lineTx = pipeSide.modTyp.modeCR; new servPcepConn(this, id.peerAddr.copyBytes(), pipe); return false; } } class servPcepConn implements Runnable { public servPcep lower; public addrIP peer; public pipeSide conn; public servPcepConn(servPcep parent, addrIP remote, pipeSide pipe) { lower = parent; peer = remote; conn = pipe; new Thread(this).start(); } public void doWork() { packPcep pck = new packPcep(); pck.pipe = conn; pck.createOpen(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); pck.createKeep(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); if (pck.recvPack()) { return; } if (debugger.servPcepTraf) { logger.debug("rx " + pck); } if (pck.msgTyp != packPcep.typOpen) { return; } if (lower.logging) { logger.warn("neighbor " + peer + " up"); } long lastKeep = 0; for (;;) { pck = new packPcep(); pck.pipe = conn; long tim = bits.getTime(); if ((tim - lastKeep) > 30000) { pck.createKeep(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); lastKeep = tim; } if (pck.recvPack()) { return; } if (debugger.servPcepTraf) { logger.debug("rx " + pck); } if (pck.msgTyp != packPcep.typReq) { continue; } if (lower.logging) { logger.warn("request " + peer + " type=" + pck.setupType + " " + pck.srcAddr + " -> " + pck.trgAddr); } pck.ero = null; pck.loose = true; if (lower.expVrf == null) { pck.createReply(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); continue; } ipFwd fwd; if (pck.isIP4) { fwd = lower.expVrf.fwd4; } else { fwd = lower.expVrf.fwd6; } tabRouteEntry ntry = fwd.actualU.route(pck.srcAddr); if (ntry == null) { pck.createReply(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); continue; } ntry = fwd.actualU.route(pck.trgAddr); if (ntry == null) { pck.createReply(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); continue; } pck.ero = new ArrayList(); if (ntry.best.oldHop != null) { tabRouteEntry ntry2 = fwd.actualU.route(ntry.best.oldHop); if (ntry2 != null) { tabHop mid = new tabHop(); mid.strict = false; mid.adr.setAddr(ntry.best.oldHop); if (pck.setupType == 1) { mid.index = !lower.explicit; mid.label = ntry2.best.segrouIdx; if (lower.explicit) { mid.label += ntry2.best.segrouOld; mid.label <<= 12; } } pck.ero.add(mid); } } tabHop hop = new tabHop(); hop.strict = false; hop.adr.setAddr(pck.trgAddr); if (pck.setupType == 1) { hop.index = !lower.explicit; hop.label = ntry.best.segrouIdx; if (lower.explicit) { hop.label += ntry.best.segrouOld; hop.label <<= 12; } } pck.ero.add(hop); pck.createReply(); if (debugger.servPcepTraf) { logger.debug("tx " + pck); } pck.sendPack(); } } public void run() { try { doWork(); } catch (Exception e) { logger.traceback(e); } if (lower.logging) { logger.error("neighbor " + peer + " down"); } conn.setClose(); } }