private void PerformLabelAction(MPLSPackage package, NHLFETableRow NHLFE, byte TTL, ref string poppedLabelStack) { if (NHLFE.OutPort != null) { package.Port = (ushort)NHLFE.OutPort; } switch (NHLFE.Action) { case LabelActions.POP: if (poppedLabelStack.Equals("-")) { poppedLabelStack = package.PeekTopLabel().Number.ToString(); } else { poppedLabelStack += "," + package.PeekTopLabel().Number.ToString(); } AddLog($"Popped top label: {package.PeekTopLabel().Number}", LogType.Information, Window.ShowDetailedRoutingLogs); package.PopTopLabel(); if (package.LabelStack.IsEmpty()) { AddLog("[MPLS->IP] Copying TTL from MPLS level 1 label to IP header", LogType.Information, Window.ShowDetailedTTLLogs); package.TTL = TTL; } else { AddLog("[MPLS] Copying TTL from the previous outermost label to the new [lower level] outermost one", LogType.Information, Window.ShowDetailedTTLLogs); package.PeekTopLabel().TTL = TTL; } break; case LabelActions.SWAP: AddLog($"Swapped top label: {package.PeekTopLabel().Number} to {(short)NHLFE.OutLabel}", LogType.Information, Window.ShowDetailedRoutingLogs); package.PopTopLabel(); package.PushLabel(new Label((short)NHLFE.OutLabel)); package.PeekTopLabel().TTL = TTL; break; case LabelActions.PUSH: AddLog($"Pushed new label: {(short)NHLFE.OutLabel}", LogType.Information, Window.ShowDetailedRoutingLogs); package.PushLabel(new Label((short)NHLFE.OutLabel)); if (poppedLabelStack.Equals("Push first label on IP package")) { AddLog("[MPLS] Copying TTL from IP header", LogType.Information, Window.ShowDetailedTTLLogs); poppedLabelStack = "-"; } else { AddLog("[MPLS] Copying TTL from the previous outermost label to the new [higher level] outermost one", LogType.Information, Window.ShowDetailedTTLLogs); } package.PeekTopLabel().TTL = TTL; break; default: break; } }
private MPLSPackage PerformMplsNotEmptyPacketRouting(MPLSPackage package) { var labelTTL = package.PeekTopLabel().TTL; string poppedLabelStack = "-"; while (true) { if (package.LabelStack.IsEmpty()) // in case if we are egress LER { return(package); } AddLog($"Looking for NHLFE_ID in ILM table...", LogType.Information, Window.ShowDetailedRoutingLogs); var ilmRow = RoutingTables.ilmTable.Rows.FirstOrDefault(row => row.IncPort == package.Port && package.PeekTopLabel().Number == (short)row.IncLabel && poppedLabelStack.Equals(row.PoppedLabelStack)); // After completing previous NHFLE action (with nextID==null), check, if there is any rule for such (incPort, incLabel, poppedLabelStack) entry // i.e. let's say that we popped one label in the previous action. We couldn't have NEXT_ID filled, because router can only see what is in the outermost label. // But in order to disgunish, for example, label 17 that was nested from label 17 that was not, we must remember a stack of labels that have been popped. // See Tools/Table Rows/IlmTableRow.cs/incLabel description for more detailed explanation. if (ilmRow == null) { AddLog($"Couldn't find matching entry!", LogType.CantFindMatchingEntry, Window.ShowDetailedRoutingLogs); return(null); } AddLog($"NHLFE_ID for incoming port={package.Port}, incoming label={package.PeekTopLabel().Number}, popped labels={(poppedLabelStack == "-" ? "NULL" : poppedLabelStack)}, is: {ilmRow.NHLFE_ID}", LogType.Information, Window.ShowDetailedRoutingLogs); var currentNHLFE = RoutingTables.nhlfeTable.Rows.FirstOrDefault(row => row.ID == ilmRow.NHLFE_ID); if (currentNHLFE == null) { // routing information is missing AddLog($"Couldn't find NHLFE entry!", LogType.Error, Window.ShowDetailedRoutingLogs); return(null); } while (true) { if (Window.ShowDetailedRoutingLogs) { string nextAction, outputPort, outputLabel; nextAction = currentNHLFE.NextID == null ? "NULL" : currentNHLFE.NextID.ToString(); outputPort = currentNHLFE.OutPort == null ? "NULL" : currentNHLFE.OutPort.ToString(); outputLabel = currentNHLFE.OutLabel == null ? "NULL" : currentNHLFE.OutLabel.ToString(); AddLog($"Action for NHLFE_ID={currentNHLFE.ID} is {currentNHLFE.Action}, output port: {outputPort}, output label: {outputLabel}, next NHLFE_ID: {nextAction}", LogType.Information, Window.ShowDetailedRoutingLogs); } var thereIsNextAction = currentNHLFE.NextID != null; PerformLabelAction(package, currentNHLFE, labelTTL, ref poppedLabelStack); // after doing SWAP, the next action will be delivered via NEXT_ID, not ILM entry. Same thing for PUSH. // if there is no next action id, then it means that we can forward the packet if (!thereIsNextAction && (currentNHLFE.Action.Equals("SWAP") || currentNHLFE.Action.Equals("PUSH"))) { AddLog($"Completed last action, forwarding to port {package.Port}", LogType.Information, Window.ShowDetailedRoutingLogs); return(package); } // this means that we popped a label and the next action - push or swap - will be determined via ILM entry if (!thereIsNextAction) { break; } currentNHLFE = RoutingTables.nhlfeTable.Rows.FirstOrDefault(row => row.ID == currentNHLFE.NextID); } } }
private void HandlePackage(MPLSPackage package) { MPLSPackage routedPackage = null; routedPackage = packageSwitch.RouteMPLSPackage(package, networkNodeRoutingTables, Window); if (routedPackage == null) { return; } try { ConnectedSocket.Send(routedPackage); AddLog( $"Package {package} routed to port {routedPackage.Port} with label {routedPackage.PeekTopLabel()?.Number.ToString() ?? "None"}", LogType.Sent); } catch (Exception e) { AddLog($"Package {routedPackage} not sent correctly: {e.Message}", LogType.Error); } }