29
29
from sdx_pce .utils .constants import Constants
30
30
from sdx_pce .utils .exceptions import (
31
31
RequestValidationError ,
32
+ SameSwitchRequestError ,
32
33
TEError ,
33
34
UnknownRequestError ,
34
35
ValidationError ,
@@ -412,6 +413,14 @@ def generate_traffic_matrix(self, connection_request: dict) -> TrafficMatrix:
412
413
f"ingress_port.id: { ingress_port .id } , "
413
414
f"egress_port.id: { egress_port .id } "
414
415
)
416
+ if ingress_port .id == egress_port .id :
417
+ self ._logger .warning (
418
+ f"Source and destination ports are the same: { ingress_port .id } "
419
+ )
420
+ raise RequestValidationError (
421
+ f"Source and destination ports are the same: { ingress_port .id } " ,
422
+ 400 ,
423
+ )
415
424
416
425
topology = self .topology_manager .get_topology ()
417
426
@@ -430,6 +439,24 @@ def generate_traffic_matrix(self, connection_request: dict) -> TrafficMatrix:
430
439
)
431
440
return None
432
441
442
+ if ingress_node == egress_node :
443
+ self ._logger .warning (
444
+ f"Source and destination nodes are the same: { ingress_node .id } "
445
+ )
446
+ domain_id = self .topology_manager .get_domain_name (ingress_node .id )
447
+ ingress_user_port_tag = ingress_port .vlan_range
448
+ egree_user_port_tag = egress_port .vlan_range
449
+ self ._logger .info (f"Same switch request: { domain_id } " )
450
+ raise SameSwitchRequestError (
451
+ f"Source and destination nodes are the same: { ingress_node .id } " ,
452
+ request .id ,
453
+ domain_id ,
454
+ ingress_port .id ,
455
+ egress_port .id ,
456
+ ingress_user_port_tag ,
457
+ egree_user_port_tag ,
458
+ )
459
+
433
460
ingress_nodes = [
434
461
x for x , y in self .graph .nodes (data = True ) if y ["id" ] == ingress_node .id
435
462
]
@@ -581,6 +608,77 @@ def add_breakdowns_to_connection(self, connection_request: dict, breakdowns: dic
581
608
582
609
return connection_request
583
610
611
+ # Special case: endpoints on the same device, no need to call the solver, only need vlan assignment
612
+ def generate_connection_breakdown_same_switch (
613
+ self ,
614
+ request_id ,
615
+ domain ,
616
+ ingress_port_id : str ,
617
+ egress_port_id : str ,
618
+ ingress_port_tag ,
619
+ egress_port_tag ,
620
+ ):
621
+ """
622
+ Generate a breakdown for a connection request where the source and destination ports are the same.
623
+ """
624
+ ingress_port = self .topology_manager .get_port_by_id (ingress_port_id )
625
+ egress_port = self .topology_manager .get_port_by_id (egress_port_id )
626
+
627
+ self ._logger .debug (
628
+ f"ingress_port: { ingress_port_id } , egress_port: { egress_port_id } , ingress_port_tag: { ingress_port_tag } , egress_port_tag: { egress_port_tag } "
629
+ )
630
+
631
+ ingress_vlan = self ._reserve_vlan (
632
+ domain ,
633
+ ingress_port ,
634
+ request_id ,
635
+ ingress_port_tag ,
636
+ None ,
637
+ )
638
+
639
+ egress_vlan = self ._reserve_vlan (
640
+ domain ,
641
+ egress_port ,
642
+ request_id ,
643
+ egress_port_tag ,
644
+ None ,
645
+ )
646
+
647
+ if ingress_vlan is None or egress_vlan is None :
648
+ self ._logger .error (
649
+ f"ingress_vlan: { ingress_vlan } , egress_vlan: { egress_vlan } . "
650
+ f"Can't proceed. Rolling back reservations."
651
+ )
652
+ self .unreserve_vlan (request_id = request_id )
653
+ raise TEError (f"Can't find a vlan assignment for: { request_id } " , 410 )
654
+
655
+ self ._logger .debug (f"ingress_vlan: { ingress_vlan } , egress_vlan: { egress_vlan } " )
656
+
657
+ tag_type = 0 if ingress_vlan == "untagged" else 1
658
+ port_a = VlanTaggedPort (
659
+ VlanTag (value = ingress_vlan , tag_type = tag_type ), port_id = ingress_port_id
660
+ )
661
+ tag_type = 0 if egress_vlan == "untagged" else 1
662
+ port_z = VlanTaggedPort (
663
+ VlanTag (value = egress_vlan , tag_type = tag_type ), port_id = egress_port_id
664
+ )
665
+
666
+ # Names look like "AMLIGHT_vlan_201_202_Ampath_Tenet". We
667
+ # can form the initial part, but where did the
668
+ # `Ampath_Tenet` at the end come from?
669
+ domain_name = domain .split (":" )[- 1 ].split ("." )[0 ].upper ()
670
+ name = f"{ domain_name } _vlan_{ ingress_vlan } _{ egress_vlan } "
671
+ breakdowns = {}
672
+ breakdown = VlanTaggedBreakdown (
673
+ name = name ,
674
+ dynamic_backup_path = True ,
675
+ uni_a = port_a ,
676
+ uni_z = port_z ,
677
+ )
678
+ breakdowns [domain ] = breakdown .to_dict ()
679
+ return breakdowns
680
+
681
+ # General case
584
682
def generate_connection_breakdown (
585
683
self , solution : ConnectionSolution , connection_request : dict
586
684
) -> dict :
@@ -1236,7 +1334,7 @@ def _reserve_vlan(
1236
1334
# with self._topology_lock:
1237
1335
# pass
1238
1336
1239
- self ._logger .debug (
1337
+ self ._logger .info (
1240
1338
f"Reserving VLAN for domain: { domain } , port: { port } , "
1241
1339
f"request_id: { request_id } , tag:{ tag } "
1242
1340
)
@@ -1262,6 +1360,7 @@ def _reserve_vlan(
1262
1360
self ._logger .warning (
1263
1361
f"Can't find a VLAN table for domain: { domain } port: { port_id } "
1264
1362
)
1363
+ self ._logger .warning (f"Available ports: { domain_table .keys ()} " )
1265
1364
return None
1266
1365
1267
1366
if tag is None :
0 commit comments