diff --git a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go index 80bd06a39..27b4799e5 100644 --- a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go @@ -15,6 +15,7 @@ package ipvs import ( + "sort" "strings" "github.com/dpvs-agent/models" @@ -73,11 +74,57 @@ func (h *postVsRs) Handle(params apiVs.PostVsVipPortRsParams) middleware.Respond rss[i].SetInhibited(&inhibited) } + update := !*params.PassiveUpdate + shareSnapshot := settings.ShareSnapshot() if shareSnapshot.ServiceLock(params.VipPort) { defer shareSnapshot.ServiceUnlock(params.VipPort) } + // default passiveUpdate == false + if *params.PassiveUpdate { + // passiveUpdate == true + vsModel := shareSnapshot.ServiceGet(params.VipPort) + if vsModel == nil { + h.logger.Info("Try update update. vs not found in snapshot.", "VipPort", params.VipPort) + update = true + } + + if vsModel != nil { + if len(vsModel.RSs.Items) != len(rss) { + h.logger.Info("Try update update. vs rss len has changed.", "VipPort", params.VipPort) + update = true + } + + if len(vsModel.RSs.Items) == len(rss) { + cacheRSs := (types.SliceRealServerSpecExpandModel)(vsModel.RSs.Items) + sort.Sort(cacheRSs) + + newRSs := (types.SliceRealServerSpec)(rss) + sort.Sort(newRSs) + + for i, newRs := range newRSs { + cacheRs := cacheRSs[i] + if int(cacheRs.Spec.Weight) != int(newRs.GetWeight()) { + h.logger.Info("Try update update. rs weight has changed.", "VipPort", params.VipPort, "rs", newRs.ID(), "cache weight", cacheRs.Spec.Weight, "update weight", newRs.GetWeight()) + update = true + break + } + + if !strings.EqualFold(strings.ToUpper(cacheRs.Spec.Mode), strings.ToUpper(newRs.GetFwdModeString())) { + h.logger.Info("Try update update. rs nat mode has changed.", "VipPort", params.VipPort, "rs", newRs.ID(), "cache nat mode", cacheRs.Spec.Mode, "update nat mode", newRs.GetFwdModeString()) + update = true + break + } + } + } + } + } + + if !update { + return apiVs.NewPostVsVipPortRsOK().WithPayload("PassiveUpdate") + } + result := front.Update(rss, h.connPool, h.logger) switch result { case types.EDPVS_EXIST, types.EDPVS_OK: diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go index 52328290d..9fbc51c86 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -90,7 +90,54 @@ func (h *putVsItem) Handle(params apiVs.PutVsVipPortParams) middleware.Responder } } + update := !*params.PassiveUpdate + shareSnapshot := settings.ShareSnapshot() + if shareSnapshot.ServiceRLock(vs.ID()) { + vsModel := shareSnapshot.ServiceGet(vs.ID()) + if vsModel == nil { + shareSnapshot.ServiceRUnlock(vs.ID()) + return apiVs.NewPutVsVipPortInvalidBackend() + } + + if *params.PassiveUpdate { + // bypass VIP, Port, Protocol, Af, netmask + if vsModel.Fwmark != vs.GetFwmark() || + vsModel.ConnTimeout != vs.GetConnTimeout() || + vsModel.Bps != vs.GetBps() || + vsModel.LimitProportion != vs.GetLimitProportion() { + + h.logger.Info("Try to update !!! Fwmark | ConnTimeout | Bps | LimitProportion has Changed.", "VipPort", params.VipPort) + + update = true + } + + // ExpireQuiescent | SynProxy | Quic | Persistence + newFlags := vs.GetFlags() + newFlagsNOT := ^newFlags + tmpFlags := vsModel.RAMFlags ^ newFlagsNOT + if (tmpFlags & vsModel.RAMFlags) != newFlags { + + h.logger.Info("Try to update !!! the flags has changed.", "VipPort", params.VipPort) + + update = true + } + + if !strings.EqualFold(vs.GetSchedName(), vsModel.SchedName) { + + h.logger.Info("Try to update !!! the SchedName has changed.", "VipPort", params.VipPort) + + update = true + } + } + + shareSnapshot.ServiceRUnlock(vs.ID()) + } + + if !update { + return apiVs.NewPutVsVipPortOK().WithPayload("PassiveUpdate") + } + result := vs.Add(h.connPool, h.logger) h.logger.Info("Add virtual server done.", "vs", vs, "result", result.String()) switch result { diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index 3e7653519..eb2257a9d 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -156,6 +156,12 @@ parameters: - off default: unset required: false + passive-update: + name: passiveUpdate + in: query + type: boolean + default: false + required: false version: name: version in: query @@ -561,6 +567,9 @@ definitions: format: "uint32" Flags: type: "string" + RamFlags: + type: "integer" + format: "uint32" SynProxy: type: "string" enum: @@ -1164,6 +1173,7 @@ paths: tags: - "virtualserver" parameters: + - "$ref": "#/parameters/passive-update" - "$ref": "#/parameters/snapshot" - "$ref": "#/parameters/service-id" - "$ref": "#/parameters/vs-config" @@ -1381,6 +1391,7 @@ paths: tags: - "virtualserver" parameters: + - "$ref": "#/parameters/passive-update" - "$ref": "#/parameters/snapshot" - "$ref": "#/parameters/service-id" - "$ref": "#/parameters/rss-config" diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go index 21482cc6e..df5cd6af0 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_expand.go +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -77,6 +77,9 @@ type VirtualServerSpecExpand struct { // r ss RSs *RealServerExpandList `json:"RSs,omitempty"` + // Ram flags + RAMFlags uint32 `json:"RamFlags,omitempty"` + // sched name // Enum: [rr wrr wlc conhash] SchedName string `json:"SchedName,omitempty"` diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go index 36be36731..6dcf9e56d 100644 --- a/tools/dpvs-agent/pkg/ipc/types/getmodel.go +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -37,6 +37,7 @@ func (vs *VirtualServerSpec) GetModel() *models.VirtualServerSpecExpand { Match: vs.match.GetModel(), Stats: vs.stats.GetModel(), DestCheck: vs.GetDestCheck(), + RAMFlags: vs.GetFlags(), } flags := "" diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go index 55add3ed4..ec0172b31 100644 --- a/tools/dpvs-agent/pkg/ipc/types/realserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -31,6 +31,20 @@ import ( "github.com/dpvs-agent/pkg/ipc/pool" ) +type SliceRealServerSpec []*RealServerSpec + +func (rss SliceRealServerSpec) Len() int { + return len(rss) +} + +func (rss SliceRealServerSpec) Swap(i, j int) { + rss[i], rss[j] = rss[j], rss[i] +} + +func (rss SliceRealServerSpec) Less(i, j int) bool { + return rss[i].ID() < rss[j].ID() +} + type RealServerSpec struct { af uint32 port uint16 diff --git a/tools/dpvs-agent/pkg/ipc/types/snapshot.go b/tools/dpvs-agent/pkg/ipc/types/snapshot.go index 28b713b08..bbe1adfdb 100644 --- a/tools/dpvs-agent/pkg/ipc/types/snapshot.go +++ b/tools/dpvs-agent/pkg/ipc/types/snapshot.go @@ -207,6 +207,22 @@ func (spec *VirtualServerSpecExpandModel) ID() string { return fmt.Sprintf("%s-%d-%s", net.ParseIP(spec.Addr).String(), spec.Port, proto) } +type SliceRealServerSpecExpandModel []*models.RealServerSpecExpand + +func (rss SliceRealServerSpecExpandModel) Len() int { + return len(rss) +} + +func (rss SliceRealServerSpecExpandModel) Swap(i, j int) { + rss[i], rss[j] = rss[j], rss[i] +} + +func (rss SliceRealServerSpecExpandModel) Less(i, j int) bool { + rs1 := (*RealServerSpecExpandModel)(rss[i]) + rs2 := (*RealServerSpecExpandModel)(rss[j]) + return rs1.ID() < rs2.ID() +} + func (node *NodeSnapshot) LoadFrom(cacheFile string, logger hclog.Logger) error { content, err := os.ReadFile(cacheFile) if err != nil { diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index 323f0a90c..b822d9831 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -970,6 +970,9 @@ func init() { ], "summary": "create or update virtual server", "parameters": [ + { + "$ref": "#/parameters/passive-update" + }, { "$ref": "#/parameters/snapshot" }, @@ -1600,6 +1603,9 @@ func init() { ], "summary": "Update fully real server list to vip:port:proto", "parameters": [ + { + "$ref": "#/parameters/passive-update" + }, { "$ref": "#/parameters/snapshot" }, @@ -2482,6 +2488,10 @@ func init() { "RSs": { "$ref": "#/definitions/RealServerExpandList" }, + "RamFlags": { + "type": "integer", + "format": "uint32" + }, "SchedName": { "type": "string", "enum": [ @@ -2670,6 +2680,12 @@ func init() { "name": "link", "in": "query" }, + "passive-update": { + "type": "boolean", + "default": false, + "name": "passiveUpdate", + "in": "query" + }, "promisc": { "enum": [ "unset", @@ -3955,6 +3971,12 @@ func init() { ], "summary": "create or update virtual server", "parameters": [ + { + "type": "boolean", + "default": false, + "name": "passiveUpdate", + "in": "query" + }, { "type": "boolean", "default": true, @@ -4688,6 +4710,12 @@ func init() { ], "summary": "Update fully real server list to vip:port:proto", "parameters": [ + { + "type": "boolean", + "default": false, + "name": "passiveUpdate", + "in": "query" + }, { "type": "boolean", "default": true, @@ -5597,6 +5625,10 @@ func init() { "RSs": { "$ref": "#/definitions/RealServerExpandList" }, + "RamFlags": { + "type": "integer", + "format": "uint32" + }, "SchedName": { "type": "string", "enum": [ @@ -5785,6 +5817,12 @@ func init() { "name": "link", "in": "query" }, + "passive-update": { + "type": "boolean", + "default": false, + "name": "passiveUpdate", + "in": "query" + }, "promisc": { "enum": [ "unset", diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go index b92f98b6f..1bbaf4295 100644 --- a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go @@ -25,10 +25,14 @@ func NewPostVsVipPortRsParams() PostVsVipPortRsParams { var ( // initialize parameters with default values + passiveUpdateDefault = bool(false) + snapshotDefault = bool(true) ) return PostVsVipPortRsParams{ + PassiveUpdate: &passiveUpdateDefault, + Snapshot: &snapshotDefault, } } @@ -47,6 +51,11 @@ type PostVsVipPortRsParams struct { In: path */ VipPort string + /* + In: query + Default: false + */ + PassiveUpdate *bool /* In: body */ @@ -74,6 +83,11 @@ func (o *PostVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.M res = append(res, err) } + qPassiveUpdate, qhkPassiveUpdate, _ := qs.GetOK("passiveUpdate") + if err := o.bindPassiveUpdate(qPassiveUpdate, qhkPassiveUpdate, route.Formats); err != nil { + res = append(res, err) + } + if runtime.HasBody(r) { defer r.Body.Close() var body models.RealServerTinyList @@ -120,6 +134,30 @@ func (o *PostVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, forma return nil } +// bindPassiveUpdate binds and validates parameter PassiveUpdate from query. +func (o *PostVsVipPortRsParams) bindPassiveUpdate(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPostVsVipPortRsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("passiveUpdate", "query", "bool", raw) + } + o.PassiveUpdate = &value + + return nil +} + // bindSnapshot binds and validates parameter Snapshot from query. func (o *PostVsVipPortRsParams) bindSnapshot(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go index c596ec741..75de05dfd 100644 --- a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go @@ -18,7 +18,8 @@ import ( type PostVsVipPortRsURL struct { VipPort string - Snapshot *bool + PassiveUpdate *bool + Snapshot *bool _basePath string // avoid unkeyed usage @@ -61,6 +62,14 @@ func (o *PostVsVipPortRsURL) Build() (*url.URL, error) { qs := make(url.Values) + var passiveUpdateQ string + if o.PassiveUpdate != nil { + passiveUpdateQ = swag.FormatBool(*o.PassiveUpdate) + } + if passiveUpdateQ != "" { + qs.Set("passiveUpdate", passiveUpdateQ) + } + var snapshotQ string if o.Snapshot != nil { snapshotQ = swag.FormatBool(*o.Snapshot) diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go index 4aa52d23a..a050fd4ea 100644 --- a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go @@ -25,10 +25,13 @@ func NewPutVsVipPortParams() PutVsVipPortParams { var ( // initialize parameters with default values - snapshotDefault = bool(true) + passiveUpdateDefault = bool(false) + snapshotDefault = bool(true) ) return PutVsVipPortParams{ + PassiveUpdate: &passiveUpdateDefault, + Snapshot: &snapshotDefault, } } @@ -47,6 +50,11 @@ type PutVsVipPortParams struct { In: path */ VipPort string + /* + In: query + Default: false + */ + PassiveUpdate *bool /* In: query Default: true @@ -74,6 +82,11 @@ func (o *PutVsVipPortParams) BindRequest(r *http.Request, route *middleware.Matc res = append(res, err) } + qPassiveUpdate, qhkPassiveUpdate, _ := qs.GetOK("passiveUpdate") + if err := o.bindPassiveUpdate(qPassiveUpdate, qhkPassiveUpdate, route.Formats); err != nil { + res = append(res, err) + } + qSnapshot, qhkSnapshot, _ := qs.GetOK("snapshot") if err := o.bindSnapshot(qSnapshot, qhkSnapshot, route.Formats); err != nil { res = append(res, err) @@ -120,6 +133,30 @@ func (o *PutVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats return nil } +// bindPassiveUpdate binds and validates parameter PassiveUpdate from query. +func (o *PutVsVipPortParams) bindPassiveUpdate(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutVsVipPortParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("passiveUpdate", "query", "bool", raw) + } + o.PassiveUpdate = &value + + return nil +} + // bindSnapshot binds and validates parameter Snapshot from query. func (o *PutVsVipPortParams) bindSnapshot(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go index a88b8ca67..c2dce9b47 100644 --- a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go @@ -18,7 +18,8 @@ import ( type PutVsVipPortURL struct { VipPort string - Snapshot *bool + PassiveUpdate *bool + Snapshot *bool _basePath string // avoid unkeyed usage @@ -61,6 +62,14 @@ func (o *PutVsVipPortURL) Build() (*url.URL, error) { qs := make(url.Values) + var passiveUpdateQ string + if o.PassiveUpdate != nil { + passiveUpdateQ = swag.FormatBool(*o.PassiveUpdate) + } + if passiveUpdateQ != "" { + qs.Set("passiveUpdate", passiveUpdateQ) + } + var snapshotQ string if o.Snapshot != nil { snapshotQ = swag.FormatBool(*o.Snapshot)