@@ -38,10 +38,11 @@ acl_rule_attr_lookup_t aclMatchLookup =
38
38
{ MATCH_L4_DST_PORT_RANGE, (sai_acl_entry_attr_t )SAI_ACL_RANGE_L4_DST_PORT_RANGE },
39
39
};
40
40
41
- acl_rule_attr_lookup_t aclActionLookup =
41
+ acl_rule_attr_lookup_t aclL3ActionLookup =
42
42
{
43
- { ACTION_PACKET_ACTION, SAI_ACL_ENTRY_ATTR_PACKET_ACTION },
44
- { ACTION_MIRROR_ACTION, SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS }
43
+ { PACKET_ACTION_FORWARD, SAI_ACL_ENTRY_ATTR_PACKET_ACTION },
44
+ { PACKET_ACTION_DROP, SAI_ACL_ENTRY_ATTR_PACKET_ACTION },
45
+ { PACKET_ACTION_REDIRECT, SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT }
45
46
};
46
47
47
48
static acl_table_type_lookup_t aclTableTypeLookUp =
@@ -345,11 +346,42 @@ bool AclRule::create()
345
346
{
346
347
SWSS_LOG_ERROR (" Failed to create ACL rule" );
347
348
AclRange::remove (range_objects, range_object_list.count );
349
+ decreaseNextHopRefCount ();
348
350
}
349
351
350
352
return (status == SAI_STATUS_SUCCESS);
351
353
}
352
354
355
+ void AclRule::decreaseNextHopRefCount ()
356
+ {
357
+ if (!m_redirect_target_next_hop.empty ())
358
+ {
359
+ m_pAclOrch->m_neighOrch ->decreaseNextHopRefCount (IpAddress (m_redirect_target_next_hop));
360
+ m_redirect_target_next_hop.clear ();
361
+ }
362
+ if (!m_redirect_target_next_hop_group.empty ())
363
+ {
364
+ IpAddresses target = IpAddresses (m_redirect_target_next_hop_group);
365
+ m_pAclOrch->m_routeOrch ->decreaseNextHopRefCount (target);
366
+ // remove next hop group in case it's not used by anything else
367
+ if (m_pAclOrch->m_routeOrch ->isRefCounterZero (target))
368
+ {
369
+ if (m_pAclOrch->m_routeOrch ->removeNextHopGroup (target))
370
+ {
371
+ SWSS_LOG_DEBUG (" Removed acl redirect target next hop group '%s'" , m_redirect_target_next_hop_group.c_str ());
372
+ }
373
+ else
374
+ {
375
+ SWSS_LOG_ERROR (" Failed to remove unused next hop group '%s'" , m_redirect_target_next_hop_group.c_str ());
376
+ // FIXME: what else could we do here?
377
+ }
378
+ }
379
+ m_redirect_target_next_hop_group.clear ();
380
+ }
381
+
382
+ return ;
383
+ }
384
+
353
385
bool AclRule::remove ()
354
386
{
355
387
SWSS_LOG_ENTER ();
@@ -363,6 +395,8 @@ bool AclRule::remove()
363
395
364
396
m_ruleOid = SAI_NULL_OBJECT_ID;
365
397
398
+ decreaseNextHopRefCount ();
399
+
366
400
res = removeRanges ();
367
401
res &= removeCounter ();
368
402
@@ -477,9 +511,6 @@ bool AclRuleL3::validateAddAction(string attr_name, string _attr_value)
477
511
string attr_value = toUpper (_attr_value);
478
512
sai_attribute_value_t value;
479
513
480
- if (aclActionLookup.find (attr_name) == aclActionLookup.end ())
481
- return false ;
482
-
483
514
if (attr_name != ACTION_PACKET_ACTION)
484
515
{
485
516
return false ;
@@ -493,17 +524,116 @@ bool AclRuleL3::validateAddAction(string attr_name, string _attr_value)
493
524
{
494
525
value.aclaction .parameter .s32 = SAI_PACKET_ACTION_DROP;
495
526
}
527
+ else if (attr_value.find (PACKET_ACTION_REDIRECT) != string::npos)
528
+ {
529
+ // resize attr_value to remove argument, _attr_value still has the argument
530
+ attr_value.resize (string (PACKET_ACTION_REDIRECT).length ());
531
+
532
+ sai_object_id_t param_id = getRedirectObjectId (_attr_value);
533
+ if (param_id == SAI_NULL_OBJECT_ID)
534
+ {
535
+ return false ;
536
+ }
537
+ value.aclaction .parameter .oid = param_id;
538
+ }
496
539
else
497
540
{
498
541
return false ;
499
542
}
500
543
value.aclaction .enable = true ;
501
544
502
- m_actions[aclActionLookup[attr_name ]] = value;
545
+ m_actions[aclL3ActionLookup[attr_value ]] = value;
503
546
504
547
return true ;
505
548
}
506
549
550
+ // This method should return sai attribute id of the redirect destination
551
+ sai_object_id_t AclRuleL3::getRedirectObjectId (const string& redirect_value)
552
+ {
553
+ // check that we have a colon after redirect rule
554
+ size_t colon_pos = string (PACKET_ACTION_REDIRECT).length ();
555
+ if (redirect_value[colon_pos] != ' :' )
556
+ {
557
+ SWSS_LOG_ERROR (" Redirect action rule must have ':' after REDIRECT" );
558
+ return SAI_NULL_OBJECT_ID;
559
+ }
560
+
561
+ if (colon_pos + 1 == redirect_value.length ())
562
+ {
563
+ SWSS_LOG_ERROR (" Redirect action rule must have a target after 'REDIRECT:' action" );
564
+ return SAI_NULL_OBJECT_ID;
565
+ }
566
+
567
+ string target = redirect_value.substr (colon_pos + 1 );
568
+
569
+ // Try to parse physical port and LAG first
570
+ Port port;
571
+ if (m_pAclOrch->m_portOrch ->getPort (target, port))
572
+ {
573
+ if (port.m_type == Port::PHY)
574
+ {
575
+ return port.m_port_id ;
576
+ }
577
+ else if (port.m_type == Port::LAG)
578
+ {
579
+ return port.m_lag_id ;
580
+ }
581
+ else
582
+ {
583
+ SWSS_LOG_ERROR (" Wrong port type for REDIRECT action. Only physical ports and LAG ports are supported" );
584
+ return SAI_NULL_OBJECT_ID;
585
+ }
586
+ }
587
+
588
+ // Try to parse nexthop ip address
589
+ try
590
+ {
591
+ IpAddress ip (target);
592
+ if (!m_pAclOrch->m_neighOrch ->hasNextHop (ip))
593
+ {
594
+ SWSS_LOG_ERROR (" ACL Redirect action target next hop ip: '%s' doesn't exist on the switch" , ip.to_string ().c_str ());
595
+ return SAI_NULL_OBJECT_ID;
596
+ }
597
+
598
+ m_redirect_target_next_hop = target;
599
+ m_pAclOrch->m_neighOrch ->increaseNextHopRefCount (ip);
600
+ return m_pAclOrch->m_neighOrch ->getNextHopId (ip);
601
+ }
602
+ catch (...)
603
+ {
604
+ // no error, just try next variant
605
+ }
606
+
607
+ // try to parse nh group ip addresses
608
+ try
609
+ {
610
+ IpAddresses ips (target);
611
+ if (!m_pAclOrch->m_routeOrch ->hasNextHopGroup (ips))
612
+ {
613
+ SWSS_LOG_INFO (" ACL Redirect action target next hop group: '%s' doesn't exist on the switch. Creating it." , ips.to_string ().c_str ());
614
+
615
+ if (!m_pAclOrch->m_routeOrch ->addNextHopGroup (ips))
616
+ {
617
+ SWSS_LOG_ERROR (" Can't create required target next hop group '%s'" , ips.to_string ().c_str ());
618
+ return SAI_NULL_OBJECT_ID;
619
+ }
620
+ SWSS_LOG_DEBUG (" Created acl redirect target next hop group '%s'" , ips.to_string ().c_str ());
621
+ }
622
+
623
+ m_redirect_target_next_hop_group = target;
624
+ m_pAclOrch->m_routeOrch ->increaseNextHopRefCount (ips);
625
+ return m_pAclOrch->m_routeOrch ->getNextHopGroupId (ips);
626
+ }
627
+ catch (...)
628
+ {
629
+ // no error, just try next variant
630
+ }
631
+
632
+ SWSS_LOG_ERROR (" ACL Redirect action target '%s' wasn't recognized" , target.c_str ());
633
+
634
+ return SAI_NULL_OBJECT_ID;
635
+ }
636
+
507
637
bool AclRuleL3::validateAddMatch (string attr_name, string attr_value)
508
638
{
509
639
if (attr_name == MATCH_DSCP)
@@ -805,10 +935,12 @@ bool AclRange::remove()
805
935
return true ;
806
936
}
807
937
808
- AclOrch::AclOrch (DBConnector *db, vector<string> tableNames, PortsOrch *portOrch, MirrorOrch *mirrorOrch) :
938
+ AclOrch::AclOrch (DBConnector *db, vector<string> tableNames, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch ) :
809
939
Orch(db, tableNames),
810
940
m_portOrch(portOrch),
811
- m_mirrorOrch(mirrorOrch)
941
+ m_mirrorOrch(mirrorOrch),
942
+ m_neighOrch(neighOrch),
943
+ m_routeOrch(routeOrch)
812
944
{
813
945
SWSS_LOG_ENTER ();
814
946
0 commit comments