rust_rsm/alg/
spf.rs

1/* spf.rs
2日期:2022-9-3
3
4最短路径算法,给定一个开销矩阵,计算任意两点之间最大的路径长度
5目前最大支持1024个节点,入参的每个节点用整形的ID确定
6
7已经支持:
81、增删节点
92、增删链路
103、更新链路Metric值
114、基于Priority Queue优化的Dijkstra算法
125、按源节点计算最短路径
136、计算所有的最短路径
147、一对节点间多链路,以支持设备多接口的场景;包括MANET网络结构下的路由
15
16尚未支持的:
171、ECMP
182、PRC路由计算
193、路径变化通知
20*/
21#![allow(non_camel_case_types)]
22#![allow(non_snake_case)]
23#![allow(non_upper_case_globals)]
24#![allow(dead_code)]
25
26use crate::common::errcode;
27use crate::common::TsIdAllocator;
28//use crate::common::TsHashMap;
29use std::collections::HashMap;
30use std::mem;
31use std::alloc;
32use super::*;
33
34type T_NODE_INDEX=u16;
35
36
37const INVALID_NODE_ID:u16 = u16::MAX;
38pub const METRIC_INFINITY:u16 = u16::MAX;
39const SPF_MAX_LINK_PER_PAIR:u16 = 4; //每对Node之间最大的链路数量
40
41/*一对节点间允许多个链路的情况下,每个链路都有自己的Metric*/
42#[derive(Clone)]
43pub struct port_pair_t {
44	src_port_id:u32, 
45    dst_port_id:u32,
46	metric:u32,
47}
48
49///path edge,represent one edge of the path
50#[derive(Clone)]
51pub struct path_edge_t {
52    dst_node_id:u32,
53    src_port_id:u32,
54    dst_port_id:u32,
55	metric:u32,
56}
57
58///path_node,represent one none in path, include multiple edges
59#[derive(Clone)]
60pub struct path_node_t {
61	src_node_id:u32,
62    edges:Vec<path_edge_t>,
63}
64
65/*一条边的信息,dst_node_id和src_node_id都按ID编号*/
66
67#[derive(Clone)]
68pub struct edge_t {
69    src_node_id:T_NODE_INDEX,
70    dst_node_id:T_NODE_INDEX,
71    link_count:u16,
72	metric:u32,
73	best_link:u16,
74	links:[port_pair_t;SPF_MAX_LINK_PER_PAIR as usize],
75}
76
77#[derive(Clone)]
78pub struct edge_info_t {
79	edge:edge_t,
80	changed:bool,
81}
82
83type path_t=Vec<path_node_t>;
84
85/*用于计算的开销矩阵*/
86pub struct spf_matrix_t {
87	node_count:usize,
88	max_node_idx:i32,
89	idx_alloc:TsIdAllocator,
90	idx2id:HashMap<i32,u32>, //节点的索引序号和ID号的对应关系
91	id2idx:HashMap<u32,i32>, //节点的ID号到序号的映射关系
92	cost_matrix:* mut [[edge_info_t;SPF_MAX_NODE_NUM];SPF_MAX_NODE_NUM],
93    //path vector, store the shortest distance predecessor;
94	path_vector: * mut [[Vec<T_NODE_INDEX>;SPF_MAX_NODE_NUM];SPF_MAX_NODE_NUM],
95}
96
97/*创建一个开销矩阵,并进行初始化;Node Index从0开始编号*/
98impl spf_matrix_t {
99
100pub fn new()->Self {
101
102    let cm = unsafe {
103        alloc::alloc(alloc::Layout::from_size_align_unchecked(SPF_MAX_NODE_NUM*SPF_MAX_NODE_NUM*mem::size_of::<edge_info_t>(), 1)) 
104		as * mut [[edge_info_t;SPF_MAX_NODE_NUM];SPF_MAX_NODE_NUM]    
105    };
106	let pv = unsafe {
107		alloc::alloc(alloc::Layout::from_size_align_unchecked(SPF_MAX_NODE_NUM*SPF_MAX_NODE_NUM*mem::size_of::<path_t>(), 1)) 
108		as * mut [[Vec<T_NODE_INDEX>;SPF_MAX_NODE_NUM];SPF_MAX_NODE_NUM]
109	};
110
111	let pcm=unsafe {&mut *cm};
112    let ppv=unsafe {&mut *pv};
113
114	for i in 0..SPF_MAX_NODE_NUM {
115		for j in 0..SPF_MAX_NODE_NUM {
116			pcm[i][j].changed = false;
117			pcm[i][j].edge.src_node_id = i as u16;
118			pcm[i][j].edge.dst_node_id = j as u16;
119			if i == j {
120				pcm[i][j].edge.metric = 0;
121			} else {
122				pcm[i][j].edge.metric = METRIC_INFINITY as u32;
123			}
124            let path=Vec::new();
125            ppv[i][j]=path;
126
127		}
128	}
129
130	return spf_matrix_t {
131		node_count:0,
132		idx_alloc:TsIdAllocator::new(0, SPF_MAX_NODE_NUM as i32),
133		idx2id:HashMap::with_capacity(SPF_MAX_NODE_NUM),
134		id2idx:HashMap::with_capacity(SPF_MAX_NODE_NUM),
135		cost_matrix:cm,
136		path_vector:pv,
137		max_node_idx:-1,
138	}
139}
140
141/*加入一个Node,用NodeId表示;内部用idx进行管理计算*/
142pub fn add_node(&mut self,node_id:u32)->errcode::RESULT {
143
144	if self.node_count >= SPF_MAX_NODE_NUM {
145		return errcode::ERROR_OUTOF_MEM;
146	}
147
148	if self.id2idx.contains_key(&node_id) {
149		return errcode::ERROR_ALREADY_EXIST
150	}
151
152	/*分配一个索引值*/
153	let idx = self.idx_alloc.allocate_id();
154	//fmt.Printf("Allocate NodeIdx,Id=%d,Index=%d\n", nodeId, idx)
155	self.id2idx.insert(node_id.clone(), idx.clone());
156	self.idx2id.insert(idx,node_id);
157	self.node_count+=1;
158	if idx>self.max_node_idx {
159		self.max_node_idx = idx;
160	}
161	println!("add node success,node_id={},idx={}",node_id,idx);
162	return errcode::RESULT_SUCCESS
163}
164
165/*删除一个节点*/
166pub fn  delete_node(&mut self,node_id:u32)->errcode::RESULT {
167	let idx = match self.id2idx.get(&node_id) {
168        None=> {
169            return errcode::ERROR_NOT_FOUND
170        },
171        Some(v)=>v.clone(),
172    };
173    self.idx_alloc.release_id(idx);
174    self.node_count-=1;
175	if idx==self.max_node_idx {
176		self.max_node_idx-=1;
177	}
178	return errcode::RESULT_SUCCESS
179}
180
181/*根据NodeID号读取索引号*/
182fn  getIndexById(&self,node_id:u32)->Option<i32> {
183	match self.id2idx.get(&node_id) {
184        None=> {
185            return None
186        },
187        Some(v)=>Some(v.clone()),
188    }
189}
190
191/*根据NodeID号读取索引号,读取不到返回INVALID_NODE_ID*/
192fn  get_nodeid_by_idx(&self,idx:u16)->Option<u32> {
193    let new_idx=idx as i32;
194	match self.idx2id.get(&new_idx) {
195        None=> {
196            return None
197        },
198        Some(v)=>Some(v.clone()),
199    }
200}
201
202/*从edge_t结构体中查找一个端口对是否存在,返回下标索引;否则返回INVALID_INDEX*/
203fn find_link_from_node(&self,edge:&edge_t, src_port_id:u32, dst_port:u32)->u16 {
204	for i in 0..edge.link_count as usize {
205		if edge.links[i].src_port_id == src_port_id && edge.links[i].dst_port_id == dst_port {
206			return i as u16
207		}
208	}
209
210	return u16::MAX
211}
212
213/*给指定的节点对添加一条链路,返回是否有实质修改,并且自动更新EDGE中的最佳链路和Metric*/
214fn addLinkForNode(&mut self,edge:&mut edge_t, srcPort:u32, dstPort:u32, metric:u16)->bool {
215	let idx = self.find_link_from_node(edge, srcPort, dstPort);
216	let uMetric=metric as u32;
217	if edge.link_count >= SPF_MAX_LINK_PER_PAIR || idx != u16::MAX {
218		return false
219	}
220
221	edge.links[edge.link_count as usize].src_port_id = srcPort;
222	edge.links[edge.link_count as usize].dst_port_id = dstPort;
223	edge.links[edge.link_count as usize].metric = uMetric;
224
225	let mut ret = false;
226	if uMetric < edge.metric {
227		edge.metric = uMetric;
228		edge.best_link = edge.link_count;
229		ret = true
230	}
231	edge.link_count+=1;
232
233	return ret
234
235}
236
237/*更新链路的最佳路径情况*/
238fn update_best_link(&mut self,edge:&mut edge_t)->bool {
239
240	let mut idx=u16::MAX;
241	let mut m = METRIC_INFINITY as u32;
242	for i in 0..edge.link_count {
243		if edge.links[i as usize].metric < m {
244			m = edge.links[i as usize].metric;
245			idx = i
246		}
247	}
248
249	if edge.metric == m {
250		return false
251	} 
252	edge.best_link = idx;
253	edge.metric = m;
254
255	return true
256}
257
258/*给指定的节点对删除一条链路,返回是否形成实际修改,并且自动更新EDGE中的最佳链路和Metric*/
259fn deleteLinkForNode(&mut self,edge:&mut edge_t, srcPort:u32, dstPort:u32)->bool {
260	let idx = self.find_link_from_node(edge, srcPort, dstPort);
261
262	if idx == u16::MAX {
263		return false
264	}
265
266	/*删除链路的操作实际上是移动链路*/
267	for i in idx..edge.link_count-1 {
268		edge.links[i as usize] = edge.links[i as usize+1].clone();
269	}
270
271	edge.link_count-=1;
272
273	return self.update_best_link(edge)
274}
275
276/*给指定的节点对更新一条链路,返回是否确实发生变化,并且自动更新EDGE中的最佳链路和Metric*/
277fn updateLinkForNode(&mut self,edge:&mut edge_t, srcPort:u32, dstPort:u32, metric:u16)->bool {
278	let idx = self.find_link_from_node(edge, srcPort, dstPort);
279
280	if idx == u16::MAX {
281		return false
282	}
283
284	if edge.links[idx as usize].metric == metric as u32 {
285		return false
286	}
287	edge.links[idx as usize].metric = metric as u32;
288
289	return self.update_best_link(edge)
290}
291
292/*增加一条边,以及metric,Metric越小表示链路质量越好,取值建议在0~65535之间*/
293pub fn  AddEdge(&mut self,src_node_id:u32,srcPort:u32, dst_node_id:u32, dstPort:u32, metric:u16)->errcode::RESULT {
294
295	let idxSrc = match self.getIndexById(src_node_id) {
296        None=>return errcode::ERROR_NOT_FOUND,
297        Some(v)=>v as usize,
298    };
299	let idxDst = match self.getIndexById(dst_node_id) {
300        None=>return errcode::ERROR_NOT_FOUND,
301        Some(v)=>v as usize,       
302    };
303
304	/*是否需要支持两个相同节点之间有多条不同的链路*/
305    let cm=unsafe {&mut *self.cost_matrix};
306	cm[idxSrc][idxDst].changed = self.addLinkForNode(&mut cm[idxSrc][idxDst].edge, srcPort, dstPort, metric);
307
308	//fmt.Printf("Src=%d,dst=%d, orig_metric=%d,Metric=%d\n", idxSrc, idxDst, metric,
309	//	self.costMatrix[idxSrc][idxDst].edge.metric)
310	return errcode::RESULT_SUCCESS
311}
312
313/*删除一条边,实际上是将两个节点之间的Cost值设为无穷大*/
314pub fn  DeleteEdge(&mut self,src_node_id:u32, srcPort:u32, dst_node_id:u32, dstPort:u32)->errcode::RESULT {
315
316	let idxSrc = match self.getIndexById(src_node_id) {
317        None=>return errcode::ERROR_NOT_FOUND,
318        Some(v)=>v as usize,
319    };
320	let idxDst = match self.getIndexById(dst_node_id) {
321        None=>return errcode::ERROR_NOT_FOUND,
322        Some(v)=>v as usize,       
323    };
324
325    let cm=unsafe {&mut *self.cost_matrix};
326	cm[idxSrc][idxDst].changed = self.deleteLinkForNode(&mut cm[idxSrc][idxDst].edge, srcPort, dstPort);	
327	return errcode::RESULT_SUCCESS
328}
329
330/*更新一条边的metric*/
331pub fn  UpdateEdge(&mut self,src_node_id:u32, srcPort:u32, dst_node_id:u32, dstPort:u32, metric:u16)->errcode::RESULT {
332	let idxSrc = match self.getIndexById(src_node_id) {
333        None=>return errcode::ERROR_NOT_FOUND,
334        Some(v)=>v as usize,
335    };
336	let idxDst = match self.getIndexById(dst_node_id) {
337        None=>return errcode::ERROR_NOT_FOUND,
338        Some(v)=>v as usize,       
339    };
340
341    let cm=unsafe {&mut *self.cost_matrix};
342    cm[idxSrc][idxDst].changed = self.updateLinkForNode(&mut cm[idxSrc][idxDst].edge, srcPort, dstPort, metric);
343	
344
345	return errcode::RESULT_SUCCESS
346}
347
348/*计算一个源节点到系统中所有其它节点的路径,如果要计算所有的节点,应该遍历系统中所有节点进行计算*/
349pub fn  CalcOneSrcPath(&mut self,src_node_id:u32)->errcode::RESULT {
350	
351	let idxSrc = match self.getIndexById(src_node_id) {
352        None=>return errcode::ERROR_NOT_FOUND,
353        Some(v)=>v as usize,
354    };
355	//println!("[CalcOneSrcPath]begin formulate priority queue,idx_src_id={},index={}",src_node_id,idxSrc);
356	let mut dist:Vec<u32>=Vec::with_capacity(SPF_MAX_NODE_NUM);
357	let mut c=0u32;
358    let mut alt=0u32;
359	let mut pq=priority_queue_t::new();
360		
361	
362    let cm=unsafe {&mut *self.cost_matrix};
363	let max_node_idx=(self.max_node_idx+1) as usize;
364	/*初始化开销向量,dist是src到每个节点的初始距离*/
365	let prev = unsafe { &mut (&mut *self.path_vector)[idxSrc][0..max_node_idx]};
366	for n in 0..max_node_idx {
367		let k=n as usize;
368		if k == idxSrc {
369			c = 0;
370		} else {
371			c = METRIC_INFINITY as u32;//cm[idxSrc as usize][k as usize].edge.metric;
372		}
373        dist.push(c);
374		prev[k].clear();
375		prev[k].push(u16::MAX);
376
377		/*插入PriorityQueue的记录,把从源节点到系统中所有其它节点的开销插入优先级队列
378		后者会自动进行排序,排名最靠前的最先出队*/
379		pq.push_nosort(k as usize,cm[idxSrc][k].edge.metric);
380	}
381	pq.sort();
382	// /self.id2idx.end_iter();
383	
384	//计算src到所有节点的最短路径,u始终是min<distance(src,vertex)>的节点
385	//let mut first=true;
386	while pq.len()>0 {
387		let u= match pq.pop_min() { //弹出的实际上是当前和Src距离最近的一个节点
388            None=>break,
389            Some(v)=>v,
390        };
391
392		for idx in 0..pq.len() {
393			let v = match pq.get_item_by_index(idx) {
394				None=>continue,
395				Some(v)=>v,
396			};
397
398			let metric = unsafe { cm.get_unchecked(u.node_idx).get_unchecked(v.node_idx).edge.metric};
399			// /cm[u.node_idx as usize][v.node_idx as usize].edge.metric
400			if  metric >= METRIC_INFINITY as u32 {
401				continue
402			}
403			alt = unsafe { dist.get_unchecked(u.node_idx as usize)} + metric;
404			if alt>=METRIC_INFINITY as u32 {
405				continue
406			}
407			if alt < dist[v.node_idx as usize] {
408				dist[v.node_idx as usize] = alt;
409				prev[v.node_idx as usize][0] = u.node_idx as u16;
410				pq.decrease_priority(idx, alt);
411			}
412		}
413
414	}
415
416	return errcode::RESULT_SUCCESS
417}
418
419/*读取一条SPF路径,在调用CalcOne(All)SpfPath路径计算后,就可以使用本函数获得计算后的一条路径*/
420pub fn  get_spf_path(&mut self,src_node_id:u32, dst_node_id:u32)->Option<path_t> {
421	let idxSrc = match self.getIndexById(src_node_id) {
422        None=>return None,
423        Some(v)=>v as u16,
424    };
425	let idxDst = match self.getIndexById(dst_node_id) {
426        None=>return None,
427        Some(v)=>v as u16,       
428    };
429
430	//let pv = unsafe {&mut *self.path_vector};
431	let tPath = self.constructPath(idxSrc as u16, idxDst);
432
433	return tPath
434}
435
436/*进行全部路径的计算,后续考虑增加的功能:
4371、部分路径计算
4382、路径变化主动通知功能*/
439pub fn  calc_all_path(&mut self)->errcode::RESULT {
440	let mut ids=Vec::new();
441	for (node_id,_) in self.id2idx.iter() {
442		ids.push(node_id.clone());
443	}
444	//self.id2idx.end_iter();
445
446	for id in ids {		
447		self.CalcOneSrcPath(id);
448	}
449
450	return errcode::RESULT_SUCCESS
451}
452
453#[inline(always)]
454fn get_edge_metric(&self,src_node_idx:u16,dst_node_idx:u16)->u32 {
455	if src_node_idx>=SPF_MAX_NODE_NUM as u16 || dst_node_idx>=SPF_MAX_NODE_NUM as u16 {
456		return METRIC_INFINITY as u32
457	}
458	let cm=unsafe {&mut *self.cost_matrix};
459	return cm[src_node_idx as usize][dst_node_idx as usize].edge.metric;
460}
461
462/*根据路径的前驱节点表,构造一条Path*/
463fn  constructPath(&mut self, src:u16, dst:u16)->Option<path_t> {
464
465	if src==dst || src>=SPF_MAX_NODE_NUM as u16 || dst>=SPF_MAX_NODE_NUM as u16 {
466		return None;
467	}
468	let max_node_idx=(self.max_node_idx+1) as usize;
469	let prev=&mut unsafe {&mut *self.path_vector}[src as usize][0..max_node_idx];
470	if prev.len()==0 {
471		return None;
472	}
473	//println!("path {}-{},len={},content={:?}",src,dst,prev.len(),prev);
474	let mut rPath=path_t::new();
475
476	let mut cur = dst;
477	let mut next=dst;
478	let cm=unsafe {&mut *self.cost_matrix};
479	while cur != u16::MAX  {
480		let dst_node = match self.get_nodeid_by_idx(cur) {
481			None=> {
482				next=cur;
483				cur = prev[cur as usize][0];
484				continue
485			},
486			Some(i)=>i,
487		};
488		let src_node = match self.get_nodeid_by_idx(prev[cur as usize][0]) {
489			None=>{
490				break;
491			},
492			Some(i)=>i,
493		};
494		let edge = vec![path_edge_t {
495			dst_node_id:dst_node,
496			src_port_id:0,
497			dst_port_id:0,
498			metric:self.get_edge_metric(cur,next),
499		}];
500		let mut e = path_node_t{src_node_id: src_node, edges:edge};
501
502		if cur == src {
503			break
504		}
505
506		if cur < max_node_idx as u16 && prev[cur as usize][0] != u16::MAX {
507			let pEdge = &cm[prev[cur as usize][0] as usize][cur as usize].edge;
508			e.edges[0].metric = pEdge.metric;
509			e.edges[0].src_port_id = pEdge.links[pEdge.best_link as usize].src_port_id;
510			e.edges[0].dst_port_id = pEdge.links[pEdge.best_link as usize].dst_port_id;
511			rPath.push(e);
512		} else {
513			break
514		}
515		next=cur;
516		cur = prev[cur as usize][0];
517
518	}
519
520	if rPath.len()==0 {
521		return None;
522	}
523	rPath.reverse();
524
525	return Some(rPath)
526
527}
528
529pub fn  print_stats(&self) {
530	println!("Total Node={}, idToIdxMap={}, idxToIdMap={}\n",
531		self.node_count, self.id2idx.len(), self.idx2id.len());
532	//self.idxAlloc.PrintStats()
533	for i in 0..self.node_count {
534        let idx = i as i32;
535		let id = match self.idx2id.get(&idx) {
536            None=>u32::MAX,
537            Some(v)=>*v,
538        };
539
540		println!("Idx={},IdxToId[{}]={}\n", i, idx, id);
541	}
542}
543
544
545}
546
547impl Drop for spf_matrix_t {
548	fn drop(&mut self) {
549		unsafe { 
550		alloc::dealloc(self.cost_matrix as * mut u8,
551			alloc::Layout::from_size_align_unchecked(SPF_MAX_NODE_NUM*SPF_MAX_NODE_NUM*mem::size_of::<edge_info_t>(), 1));
552		
553		alloc::dealloc(self.path_vector as * mut _,
554			alloc::Layout::from_size_align_unchecked(SPF_MAX_NODE_NUM*SPF_MAX_NODE_NUM*mem::size_of::<path_t>(), 1));
555		}
556	}
557}
558
559/*文本形式显示一个路径*/
560pub fn print_path(tPath:&path_t) {
561
562	let pl = tPath.len();
563	let mut sPath = String::default();
564	for i in 0..pl{
565		sPath = format!("{}:[{}:{}-->{}:{},Metric={}]", sPath, tPath[i].src_node_id, tPath[i].edges[0].src_port_id,
566			tPath[i].edges[0].dst_node_id, tPath[i].edges[0].dst_port_id, tPath[i].edges[0].metric)
567	}
568	if pl>0 {
569		println!("Path_len={}, from {} to {}, path:{}\n", pl, tPath[0].src_node_id, tPath[pl-1].edges[0].dst_node_id, sPath);
570	} else {
571		println!("path length is zero!");
572	}
573	
574
575}
576