Skip to content

Commit d3f01a8

Browse files
arkodgmanthan-parmar-1998
authored andcommitted
perf: preallocate structs in securitypolicy processing (envoyproxy#7039)
Signed-off-by: Arko Dasgupta <arko@tetrate.io>
1 parent 2ea4258 commit d3f01a8

File tree

1 file changed

+73
-46
lines changed

1 file changed

+73
-46
lines changed

internal/gatewayapi/securitypolicy.go

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -56,31 +56,43 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security
5656
resources *resource.Resources,
5757
xdsIR resource.XdsIRMap,
5858
) []*egv1a1.SecurityPolicy {
59-
var res []*egv1a1.SecurityPolicy
6059
// SecurityPolicies are already sorted by the provider layer
6160

6261
// First build a map out of the routes and gateways for faster lookup since users might have thousands of routes or more.
6362
// For gateways this probably isn't quite as necessary.
64-
routeMap := map[policyTargetRouteKey]*policyRouteTargetContext{}
63+
routeMapSize := len(routes)
64+
gatewayMapSize := len(gateways)
65+
policyMapSize := len(securityPolicies)
66+
67+
// Pre-allocate result slice and maps with estimated capacity to reduce memory allocations
68+
res := make([]*egv1a1.SecurityPolicy, 0, len(securityPolicies))
69+
routeMap := make(map[policyTargetRouteKey]*policyRouteTargetContext, routeMapSize)
6570
for _, route := range routes {
6671
key := policyTargetRouteKey{
6772
Kind: string(route.GetRouteType()),
6873
Name: route.GetName(),
6974
Namespace: route.GetNamespace(),
7075
}
71-
routeMap[key] = &policyRouteTargetContext{RouteContext: route, attachedToRouteRules: make(sets.Set[string])}
76+
routeMap[key] = &policyRouteTargetContext{
77+
RouteContext: route,
78+
attachedToRouteRules: make(sets.Set[string]),
79+
}
7280
}
73-
gatewayMap := map[types.NamespacedName]*policyGatewayTargetContext{}
81+
82+
gatewayMap := make(map[types.NamespacedName]*policyGatewayTargetContext, gatewayMapSize)
7483
for _, gw := range gateways {
7584
key := utils.NamespacedName(gw)
76-
gatewayMap[key] = &policyGatewayTargetContext{GatewayContext: gw, attachedToListeners: make(sets.Set[string])}
85+
gatewayMap[key] = &policyGatewayTargetContext{
86+
GatewayContext: gw,
87+
attachedToListeners: make(sets.Set[string]),
88+
}
7789
}
7890

7991
// Map of Gateway to the routes attached to it.
8092
// The routes are grouped by sectionNames of their targetRefs
81-
gatewayRouteMap := make(map[string]map[string]sets.Set[string])
93+
gatewayRouteMap := make(map[string]map[string]sets.Set[string], gatewayMapSize)
8294

83-
handledPolicies := make(map[types.NamespacedName]*egv1a1.SecurityPolicy)
95+
handledPolicies := make(map[types.NamespacedName]*egv1a1.SecurityPolicy, policyMapSize)
8496

8597
// Translate
8698
// 1. First translate Policies targeting RouteRules
@@ -622,6 +634,28 @@ func (t *Translator) translateSecurityPolicyForRoute(
622634
}
623635
}
624636

637+
// Pre-create security features to avoid repeated allocations
638+
securityFeatures := &ir.SecurityFeatures{
639+
CORS: cors,
640+
JWT: jwt,
641+
OIDC: oidc,
642+
APIKeyAuth: apiKeyAuth,
643+
BasicAuth: basicAuth,
644+
ExtAuth: extAuth,
645+
Authorization: authorization,
646+
}
647+
648+
// Pre-create error response to avoid repeated allocations
649+
var errorResponse *ir.CustomResponse
650+
if errs != nil {
651+
shouldFailOpen := extAuthErr != nil && !hasNonExtAuthError && ptr.Deref(policy.Spec.ExtAuth.FailOpen, false)
652+
if !shouldFailOpen {
653+
errorResponse = &ir.CustomResponse{
654+
StatusCode: ptr.To(uint32(500)),
655+
}
656+
}
657+
}
658+
625659
irKey := t.getIRKey(gtwCtx.Gateway)
626660
for _, listener := range parentRefCtx.listeners {
627661
irListener := xdsIR[irKey].GetHTTPListener(irListenerName(listener))
@@ -640,26 +674,10 @@ func (t *Translator) translateSecurityPolicyForRoute(
640674
continue
641675
}
642676

643-
r.Security = &ir.SecurityFeatures{
644-
CORS: cors,
645-
JWT: jwt,
646-
OIDC: oidc,
647-
APIKeyAuth: apiKeyAuth,
648-
BasicAuth: basicAuth,
649-
ExtAuth: extAuth,
650-
Authorization: authorization,
651-
}
652-
if errs != nil {
653-
// If there is only error for ext auth and ext auth is set to fail open, then skip the ext auth
654-
// and allow the request to go through.
655-
// Otherwise, return a 500 direct response to avoid unauthorized access.
656-
shouldFailOpen := extAuthErr != nil && !hasNonExtAuthError && ptr.Deref(policy.Spec.ExtAuth.FailOpen, false)
657-
if !shouldFailOpen {
658-
// Return a 500 direct response to avoid unauthorized access
659-
r.DirectResponse = &ir.CustomResponse{
660-
StatusCode: ptr.To(uint32(500)),
661-
}
662-
}
677+
r.Security = securityFeatures
678+
if errorResponse != nil {
679+
// Return a 500 direct response to avoid unauthorized access
680+
r.DirectResponse = errorResponse
663681
}
664682
}
665683
}
@@ -760,6 +778,30 @@ func (t *Translator) translateSecurityPolicyForGateway(
760778
// Should exist since we've validated this
761779
x := xdsIR[irKey]
762780

781+
// Pre-create security features and error response to avoid repeated allocations
782+
securityFeatures := &ir.SecurityFeatures{
783+
CORS: cors,
784+
JWT: jwt,
785+
OIDC: oidc,
786+
APIKeyAuth: apiKeyAuth,
787+
BasicAuth: basicAuth,
788+
ExtAuth: extAuth,
789+
Authorization: authorization,
790+
}
791+
792+
var errorResponse *ir.CustomResponse
793+
if errs != nil {
794+
// If there is only error for ext auth and ext auth is set to fail open, then skip the ext auth
795+
// and allow the request to go through.
796+
// Otherwise, return a 500 direct response to avoid unauthorized access.
797+
shouldFailOpen := extAuthErr != nil && !hasNonExtAuthError && ptr.Deref(policy.Spec.ExtAuth.FailOpen, false)
798+
if !shouldFailOpen {
799+
errorResponse = &ir.CustomResponse{
800+
StatusCode: ptr.To(uint32(500)),
801+
}
802+
}
803+
}
804+
763805
policyTarget := irStringKey(policy.Namespace, string(target.Name))
764806
for _, h := range x.HTTP {
765807
// A HTTPListener name has the format namespace/gatewayName/listenerName
@@ -772,32 +814,17 @@ func (t *Translator) translateSecurityPolicyForGateway(
772814
if target.SectionName != nil && string(*target.SectionName) != h.Metadata.SectionName {
773815
continue
774816
}
817+
775818
// A Policy targeting the specific scope(xRoute rule, xRoute, Gateway listener) wins over a policy
776819
// targeting a lesser specific scope(Gateway).
777820
for _, r := range h.Routes {
778821
// if already set - there's a specific level policy, so skip.
779822
if r.Security != nil {
780823
continue
781824
}
782-
r.Security = &ir.SecurityFeatures{
783-
CORS: cors,
784-
JWT: jwt,
785-
OIDC: oidc,
786-
APIKeyAuth: apiKeyAuth,
787-
BasicAuth: basicAuth,
788-
ExtAuth: extAuth,
789-
Authorization: authorization,
790-
}
791-
if errs != nil {
792-
// If there is only error for ext auth and ext auth is set to fail open, then skip the ext auth
793-
// and allow the request to go through.
794-
// Otherwise, return a 500 direct response to avoid unauthorized access.
795-
shouldFailOpen := extAuthErr != nil && !hasNonExtAuthError && ptr.Deref(policy.Spec.ExtAuth.FailOpen, false)
796-
if !shouldFailOpen {
797-
r.DirectResponse = &ir.CustomResponse{
798-
StatusCode: ptr.To(uint32(500)),
799-
}
800-
}
825+
r.Security = securityFeatures
826+
if errorResponse != nil {
827+
r.DirectResponse = errorResponse
801828
}
802829
}
803830
}

0 commit comments

Comments
 (0)