/// <summary> /// 阻塞的方式处理控制器的消息,处理完之前无法接受控制器消息,属于监听子线程 /// </summary> /// <param name="packetInfo"></param> public static void DealControllerPacket(PacketInfo packetInfo) { int iPhyPortNo = packetInfo.GetPhyPort(); byte[] buffer = packetInfo.GetPacketByte(); PacketEntity packet = (PacketEntity)Util.BytesToObject(buffer); string content = packet.GetStrContent(); string srcIP = packet.GetHead().strSrcIP; string desIP = packet.GetHead().strDesIP; PacketHead.EN_PACKET_TYPE packetType = packet.GetHead().enPacketType; switch (packetType) { case PacketHead.EN_PACKET_TYPE.EN_ACK_SWITCH_ONLINE: Util.Log(Util.EN_LOG_LEVEL.EN_LOG_INFO, "控制器上线"); break; //收到控制器下发的流表 case PacketHead.EN_PACKET_TYPE.EN_PACKET_OUT_WITH_FLOW_ITEM: DealPacketOut(packetInfo); break; case PacketHead.EN_PACKET_TYPE.EN_PACKET_OUT_DUMP: //TODO break; default: break; } }
/// <summary> /// 处理消息队列中的消息 /// </summary> /// <param name="packetInfo">待处理的消息包</param> public static void DealReceivePacket(PacketInfo packetInfo) { int iPhyPortNo = packetInfo.GetPhyPort(); byte[] buffer = packetInfo.GetPacketByte(); PacketEntity packet = (PacketEntity)Util.BytesToObject(buffer); PacketHead.EN_PACKET_TYPE packetType = packet.GetHead().enPacketType; switch (packetType) { case PacketHead.EN_PACKET_TYPE.EN_NORMAL_PACKET: TranNormalPacket(packetInfo); break; default: break; } //Console.WriteLine("从端口" + iPhyPortNo + "收到消息:" + content); //Console.WriteLine("SrcIP: " + srcIP + "\tDesIP" + desIP); }
/// <summary> /// 处理交换机上线消息 /// </summary> /// <param name=""></param> public static void DealSwitchOnlinePacket(PacketInfo packetInfo) { byte[] packetByte = packetInfo.GetPacketByte(); int iPhyPortNo = packetInfo.GetPhyPort(); PacketEntity packet = (PacketEntity)Util.BytesToObject(packetByte); string content = packet.GetStrContent(); string srcIP = packet.GetHead().strSrcIP; string desIP = packet.GetHead().strDesIP; Const.EN_RET_CODE retVal = Const.EN_RET_CODE.EN_RET_INIT; Util.Log(Util.EN_LOG_LEVEL.EN_LOG_INFO, "交换机" + iPhyPortNo + "上线"); //回复上线消息 PacketHead head = new PacketHead("", "", PacketHead.EN_PACKET_TYPE.EN_ACK_SWITCH_ONLINE); PacketEntity ackPakcet = new PacketEntity(head, ""); retVal = Transmitter.SendViaPhyPort(iPhyPortNo, Util.ObjectToBytes(ackPakcet)); if (Const.EN_RET_CODE.EN_RET_SUCC != retVal) { Util.Log(Util.EN_LOG_LEVEL.EN_LOG_FATAL, "交换机上线ACK发送失败"); } }
/// <summary> /// 处理packet_in消息,计算最短路径后,发送packet_out消息 /// </summary> /// <param name="packetInfo"></param> public static void DealPakcetIn(PacketInfo packetInfo) { byte[] packetByte = packetInfo.GetPacketByte(); int iPhyPortNo = packetInfo.GetPhyPort(); PacketEntity packet = (PacketEntity)Util.BytesToObject(packetByte); string content = packet.GetStrContent(); string srcIP = packet.GetHead().strSrcIP; string desIP = packet.GetHead().strDesIP; Const.EN_RET_CODE retVal = Const.EN_RET_CODE.EN_RET_INIT; //Console.WriteLine("switch No : " + iPhyPortNo + "srcIP :" + srcIP + " desIP : " + desIP); //源点交换机ID int srcSwitchID = iPhyPortNo; //目的点交换机ID int desSwitchID; //目的IP有效标志 //bool isDesIPValid = true; //记录到当前点的最短路径数值 int[] distance = new int[Program.iMaxDeviceID + 1]; //标记是否在最短路径中 bool[] isInPath = new bool[Program.iMaxDeviceID + 1]; //最短路径的前驱点 int[] preSwitchID = new int[Program.iMaxDeviceID + 1]; //获取目的节点的ID try { desSwitchID = GetSwitchIDByIP(desIP); } catch (Exception) { //如果目的IP不在拓扑图中,则命令交换机丢弃数据包 Util.Log(Util.EN_LOG_LEVEL.EN_LOG_INFO, "目的IP错误"); PacketHead dumpHead = new PacketHead(srcIP, desIP, PacketHead.EN_PACKET_TYPE.EN_PACKET_OUT_DUMP); PacketEntity dumpPacket = new PacketEntity(dumpHead, ""); retVal = Transmitter.SendViaPhyPort(srcSwitchID, Util.ObjectToBytes(dumpPacket)); return; } //初始化数组 for (int i = 0; i < Program.iMaxDeviceID + 1; i++) { //设置标记为false,即未计算出到i的最短路 isInPath[i] = false; //初始化为最大值加一 distance[i] = Const.MAX_DISTANCE + 1; //前驱点设置为无效点 preSwitchID[i] = Const.INVALID_NUM; //自己到自己的路径长度设为0 if (i == srcSwitchID) { distance[i] = 0; isInPath[i] = true; } //两个交换机之间有相连路径 if (Program.PathInfoArr[srcSwitchID, i].distance != Const.INVALID_NUM) { distance[i] = Program.PathInfoArr[srcSwitchID, i].distance; //前驱暂时设置为源点 preSwitchID[i] = srcSwitchID; } } //循环n - 1次 for (int loop = 0; loop < Program.iMaxDeviceID; loop++) { int minDis = Const.MAX_DISTANCE + 1; int nextSwitchID = Const.INVALID_NUM; //找距离最小的点 for (int i = 0; i < Program.iMaxDeviceID + 1; i++) { if (!isInPath[i]) { if (distance[i] < minDis) { minDis = distance[i]; nextSwitchID = i; } } } //Console.WriteLine("next : " + nextSwitchID); //将距离最小的点加入路径 isInPath[nextSwitchID] = true; //更新数组 for (int i = 0; i < Program.iMaxDeviceID + 1; i++) { if (!isInPath[i] && (Program.PathInfoArr[nextSwitchID, i].distance != Const.INVALID_NUM)) { if (minDis + Program.PathInfoArr[nextSwitchID, i].distance < distance[i]) { distance[i] = minDis + Program.PathInfoArr[nextSwitchID, i].distance; preSwitchID[i] = nextSwitchID; } } } //如果已经找到目的交换机,则退出循环 if (nextSwitchID == desSwitchID) { break; } } //for (int i = 0; i < Program.iMaxSwitchID + 1; i++) //{ // Console.Write(preSwitchID[i] + "\t"); //} //Console.Write("\n"); Dictionary <string, int> FlowTableDic = new Dictionary <string, int>(); //遍历找到最短路的终点 for (int i = 0; i < Program.iMaxDeviceID + 1; i++) { if (!isInPath[i]) { continue; } if (i == srcSwitchID) { continue; } //TODO int curID = i; int preID = preSwitchID[curID]; //Console.WriteLine("Path: "); while (preSwitchID[preID] != Const.INVALID_NUM) { //Console.WriteLine(curID); curID = preID; preID = preSwitchID[curID]; } //此时curID是下一跳的交换机 //Console.WriteLine(curID); int transPort = Program.PathInfoArr[srcSwitchID, curID].phyPortNo; FlowTableDic.Add(GetSwitchIPByID(i), transPort); } for (int i = 0; i < FlowTableDic.Count; i++) { Console.Write(FlowTableDic.ElementAt(i).Key + "\t"); Console.Write(FlowTableDic.ElementAt(i).Value); Console.Write("\n"); } PacketHead head = new PacketHead(srcIP, desIP, PacketHead.EN_PACKET_TYPE.EN_PACKET_OUT_WITH_FLOW_ITEM); byte[] dicByte = Util.ObjectToBytes(FlowTableDic); PacketEntity packetOut = new PacketEntity(head, dicByte); //PacketEntity packetOut = new PacketEntity(head, Encoding.Default.GetBytes("asdf")); retVal = Transmitter.SendViaPhyPort(srcSwitchID, Util.ObjectToBytes(packetOut)); if (retVal != Const.EN_RET_CODE.EN_RET_SUCC) { Util.Log(Util.EN_LOG_LEVEL.EN_LOG_INFO, srcSwitchID + "号交换机路径请求发送失败"); return; } Util.Log(Util.EN_LOG_LEVEL.EN_LOG_INFO, srcSwitchID + "号交换机路径请求发送成功"); //Console.WriteLine("distance: "); //for (int i = 0; i < Program.iMaxSwitchID + 1; i++) //{ // Console.Write(distance[i] + "\t"); //} //Console.Write("\n"); }