Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BFD session get and set API added #541

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions api/models/bfd_entry.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 68 additions & 0 deletions api/models/bfd_get_entry.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/restapi/configure_loxilb_rest_api.go
Original file line number Diff line number Diff line change
@@ -135,6 +135,10 @@ func configureAPI(api *operations.LoxilbRestAPIAPI) http.Handler {
api.GetConfigCistateAllHandler = operations.GetConfigCistateAllHandlerFunc(handler.ConfigGetCIState)
api.PostConfigCistateHandler = operations.PostConfigCistateHandlerFunc(handler.ConfigPostCIState)

// BFD
api.GetConfigBfdAllHandler = operations.GetConfigBfdAllHandlerFunc(handler.ConfigGetBFDSession)
api.PostConfigBfdHandler = operations.PostConfigBfdHandlerFunc(handler.ConfigPostBFDSession)

// Firewall
api.GetConfigFirewallAllHandler = operations.GetConfigFirewallAllHandlerFunc(handler.ConfigGetFW)
api.PostConfigFirewallHandler = operations.PostConfigFirewallHandlerFunc(handler.ConfigPostFW)
334 changes: 334 additions & 0 deletions api/restapi/embedded_spec.go
47 changes: 47 additions & 0 deletions api/restapi/handler/cluster.go
Original file line number Diff line number Diff line change
@@ -62,3 +62,50 @@ func ConfigPostCIState(params operations.PostConfigCistateParams) middleware.Res
}
return &ResultResponse{Result: "Success"}
}

func ConfigGetBFDSession(params operations.GetConfigBfdAllParams) middleware.Responder {
var result []*models.BfdGetEntry
result = make([]*models.BfdGetEntry, 0)
tk.LogIt(tk.LogDebug, "[API] Status %s API called. url : %s\n", params.HTTPRequest.Method, params.HTTPRequest.URL)
bfdMod, err := ApiHooks.NetBFDGet()
if err != nil {
tk.LogIt(tk.LogDebug, "[API] Error occur : %v\n", err)
return &ResultResponse{Result: err.Error()}
}
for _, h := range bfdMod {
var tempResult models.BfdGetEntry
tempResult.Instance = h.Instance
tempResult.RemoteIP = h.RemoteIP.String()
tempResult.SourceIP = h.SourceIP.String()
tempResult.Interval = h.Interval
tempResult.Port = h.Port
tempResult.RetryCount = h.RetryCount
tempResult.State = h.State

result = append(result, &tempResult)
}

return operations.NewGetConfigBfdAllOK().WithPayload(&operations.GetConfigBfdAllOKBody{Attr: result})
}

func ConfigPostBFDSession(params operations.PostConfigBfdParams) middleware.Responder {
tk.LogIt(tk.LogDebug, "[API] HA %s API called. url : %s\n", params.HTTPRequest.Method, params.HTTPRequest.URL)

var bfdMod cmn.BFDMod

// Update BFD Session
bfdMod.Instance = params.Attr.Instance
bfdMod.RemoteIP = net.ParseIP(params.Attr.RemoteIP)
bfdMod.SourceIP = net.ParseIP(params.Attr.SourceIP)
bfdMod.Interval = params.Attr.Interval
bfdMod.RetryCount = params.Attr.RetryCount

tk.LogIt(tk.LogDebug, "[API] Instance %s BFD session update : %s, Interval: %d, RetryCount: %d\n",
bfdMod.Instance, bfdMod.RemoteIP, bfdMod.Interval, bfdMod.RetryCount)
_, err := ApiHooks.NetBFDAdd(&bfdMod)
if err != nil {
tk.LogIt(tk.LogDebug, "[API] Error occur : %v\n", err)
return &ResultResponse{Result: err.Error()}
}
return &ResultResponse{Result: "Success"}
}
166 changes: 166 additions & 0 deletions api/restapi/operations/get_config_bfd_all.go
46 changes: 46 additions & 0 deletions api/restapi/operations/get_config_bfd_all_parameters.go
194 changes: 194 additions & 0 deletions api/restapi/operations/get_config_bfd_all_responses.go
87 changes: 87 additions & 0 deletions api/restapi/operations/get_config_bfd_all_urlbuilder.go
24 changes: 24 additions & 0 deletions api/restapi/operations/loxilb_rest_api_api.go
58 changes: 58 additions & 0 deletions api/restapi/operations/post_config_bfd.go
84 changes: 84 additions & 0 deletions api/restapi/operations/post_config_bfd_parameters.go
354 changes: 354 additions & 0 deletions api/restapi/operations/post_config_bfd_responses.go
87 changes: 87 additions & 0 deletions api/restapi/operations/post_config_bfd_urlbuilder.go
122 changes: 122 additions & 0 deletions api/swagger.yml
Original file line number Diff line number Diff line change
@@ -2290,6 +2290,78 @@ paths:
schema:
type: string

#----------------------------------------------
# BFD
#----------------------------------------------
'/config/bfd/all':
get:
summary: Get BFD session inforrmation in the device
description: Get BFD session inforrmation
responses:
'200':
description: OK
schema:
type: object
properties:
Attr:
type: array
items:
$ref: '#/definitions/BfdGetEntry'
'401':
description: Invalid authentication credentials
schema:
$ref: '#/definitions/Error'
'500':
description: Internal service error
schema:
$ref: '#/definitions/Error'
'503':
description: Maintanence mode
schema:
$ref: '#/definitions/Error'

'/config/bfd':
post:
summary: Create vlan interface in the device
description: Create vlan interface in the device
parameters:
- name: attr
in: body
required: true
description: Attributes for Vlan Interface
schema:
$ref: '#/definitions/BfdEntry'
responses:
'204':
description: OK
'400':
description: Malformed arguments for API call
schema:
$ref: '#/definitions/Error'
'401':
description: Invalid authentication credentials
schema:
$ref: '#/definitions/Error'
'403':
description: Capacity insufficient
schema:
$ref: '#/definitions/Error'
'404':
description: Resource not found
schema:
$ref: '#/definitions/Error'
'409':
description: Resource Conflict. BFD session not found
schema:
$ref: '#/definitions/Error'
'500':
description: Internal service error
schema:
$ref: '#/definitions/Error'
'503':
description: Maintanence mode
schema:
$ref: '#/definitions/Error'

#----------------------------------------------
# Schema definitions
@@ -3185,3 +3257,53 @@ definitions:
listenPort:
type: integer
description: Listen port (default 179)

BfdGetEntry:
type: object
properties:
instance:
type: string
description: Instance name
remoteIp:
type: string
description: Remote IP
sourceIP:
type: string
description: Source IP to be used for BFD session
port:
type: integer
format: uint16
description: port number to be used for BFD session
interval:
type: integer
format: uint64
description: Tx interval between BFD packets(in microseconds)
retryCount:
type: integer
format: uint8
description: Retry Count to detect failure
state:
type: string
description: Current state for BFD session


BfdEntry:
type: object
properties:
instance:
type: string
description: Instance name running BFD session
remoteIp:
type: string
description: Remote IP
sourceIp:
type: string
description: Remote IP
interval:
type: integer
format: uint64
description: Tx interval between BFD packets(in microseconds)
retryCount:
type: integer
format: uint8
description: Retry Count to detect failure
22 changes: 22 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
@@ -33,6 +33,8 @@ const (
CIStateNotDefined
)

const BFDPort = 3784
const BFDDefRetryCount = 3
const (
// CIDefault - Default CI Instance name
CIDefault = "default"
@@ -660,6 +662,24 @@ type HASMod struct {
Vip net.IP `json:"Addr"`
}

// BFDMod - information related to a BFD session
type BFDMod struct {
// Instance - Cluster Instance
Instance string `json:"instance"`
// RemoteIP - Remote IP for BFD session
RemoteIP net.IP `json:"remoteIp"`
// Interval - Tx Interval between BFD packets
SourceIP net.IP `json:"sourceIp"`
// Port - BFD session port
Port uint16 `json:"port"`
// Interval - Tx Interval between BFD packets
Interval uint64 `json:"interval"`
// RetryCount - Retry Count for detecting failure
RetryCount uint8 `json:"retryCount"`
// State - BFD session state
State string `json:"state"`
}

// ClusterNodeMod - information related to a cluster node instance
type ClusterNodeMod struct {
// Instance - Cluster Instance
@@ -835,5 +855,7 @@ type NetHookInterface interface {
NetGoBGPNeighAdd(nm *GoBGPNeighMod) (int, error)
NetGoBGPNeighDel(nm *GoBGPNeighMod) (int, error)
NetGoBGPGCAdd(gc *GoBGPGlobalConfig) (int, error)
NetBFDGet() ([]BFDMod, error)
NetBFDAdd(bm *BFDMod) (int, error)
NetHandlePanic()
}
27 changes: 27 additions & 0 deletions loxinet/apiclient.go
Original file line number Diff line number Diff line change
@@ -499,6 +499,33 @@ func (na *NetAPIStruct) NetCIStateMod(hm *cmn.HASMod) (int, error) {
return 0, nil
}

// NetCIStateMod - Modify cluster state
func (na *NetAPIStruct) NetBFDGet() ([]cmn.BFDMod, error) {
if na.BgpPeerMode {
return nil, errors.New("running in bgp only mode")
}
mh.mtx.Lock()
defer mh.mtx.Unlock()

return mh.has.CIBFDSessionGet()
}

// NetCIStateMod - Modify cluster state
func (na *NetAPIStruct) NetBFDAdd(bm *cmn.BFDMod) (int, error) {
if na.BgpPeerMode {
return CIErrBase, errors.New("running in bgp only mode")
}
mh.mtx.Lock()
defer mh.mtx.Unlock()

_, err := mh.has.CIBFDSessionAdd(*bm)
if err != nil {
return -1, err
}

return 0, nil
}

// NetFwRuleAdd - Add a firewall rule in loxinet
func (na *NetAPIStruct) NetFwRuleAdd(fm *cmn.FwRuleMod) (int, error) {
if na.BgpPeerMode {
42 changes: 40 additions & 2 deletions loxinet/cluster.go
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ type CIStateH struct {
ClusterMap map[string]*ClusterInstance
StateMap map[string]int
NodeMap map[string]*ClusterNode
Bs *bfd.Struct
}

func (ci *CIStateH) BFDSessionNotify(instance string, remote string, ciState string) {
@@ -99,8 +100,9 @@ func (ci *CIStateH) startBFDProto() {
txInterval = uint32(ci.Interval)
}

bs := bfd.StructNew(3784)
bfdSessConfigArgs := bfd.ConfigArgs{RemoteIP: ci.RemoteIP.String(), SourceIP: ci.SourceIP.String(), Port: 3784, Interval: txInterval, Multi: 3, Instance: cmn.CIDefault}
bs := bfd.StructNew(cmn.BFDPort)
bfdSessConfigArgs := bfd.ConfigArgs{RemoteIP: ci.RemoteIP.String(), SourceIP: ci.SourceIP.String(),
Port: cmn.BFDPort, Interval: txInterval, Multi: cmn.BFDDefRetryCount, Instance: cmn.CIDefault}
err := bs.BFDAddRemote(bfdSessConfigArgs, ci)
if err != nil {
tk.LogIt(tk.LogCritical, "KA - Cant add BFD remote\n")
@@ -116,6 +118,8 @@ func (h *CIStateH) CITicker() {

// CISpawn - Spawn CI application
func (ci *CIStateH) CISpawn() {
bs := bfd.StructNew(3784)
ci.Bs = bs
if ci.SpawnKa {
go ci.startBFDProto()
}
@@ -264,6 +268,40 @@ func (h *CIStateH) ClusterNodeDelete(node cmn.ClusterNodeMod) (int, error) {
return 0, nil
}

// CIStateUpdate - routine to update cluster state
func (h *CIStateH) CIBFDSessionAdd(bm cmn.BFDMod) (int, error) {

if !h.SpawnKa {
tk.LogIt(tk.LogError, "[CLUSTER] Cluster Instance %s not running BFD\n", bm.Instance)
return -1, errors.New("bfd session not running")
}

_, found := h.ClusterMap[bm.Instance]
if !found {
tk.LogIt(tk.LogError, "[CLUSTER] BFD SU - Cluster Instance %s not found\n", bm.Instance)
return -1, errors.New("cluster instance not found")
}

bfdSessConfigArgs := bfd.ConfigArgs{RemoteIP: h.RemoteIP.String(), SourceIP: h.SourceIP.String(), Port: 3784, Interval: uint32(bm.Interval), Multi: bm.RetryCount, Instance: bm.Instance}
err := h.Bs.BFDAddRemote(bfdSessConfigArgs, h)
if err != nil {
tk.LogIt(tk.LogCritical, "KA - Cant add BFD remote\n")
os.Exit(1)
}
tk.LogIt(tk.LogInfo, "KA - Updated BFD remote %s:%s:%vus\n", h.RemoteIP.String(), h.SourceIP.String(), bm.Interval)
return 0, nil
}

// CIStateUpdate - routine to update cluster state
func (h *CIStateH) CIBFDSessionGet() ([]cmn.BFDMod, error) {
if !h.SpawnKa {
tk.LogIt(tk.LogError, "[CLUSTER] BFD sessions not running\n")
return nil, errors.New("bfd session not running")
}

return h.Bs.BFDGet()
}

// DP - sync state of cluster-node entity to data-path
func (cn *ClusterNode) DP(work DpWorkT) int {

51 changes: 46 additions & 5 deletions proto/bfd.go
Original file line number Diff line number Diff line change
@@ -23,8 +23,11 @@ import (
"net"
"sync"
"time"
"strings"
"strconv"

tk "github.com/loxilb-io/loxilib"
cmn "github.com/loxilb-io/loxilb/common"
)

type SessionState uint8
@@ -36,6 +39,13 @@ const (
BFDUp
)

var BFDStateMap = map[uint8]string {
uint8(BFDAdminDown):"BFDAdminDown",
uint8(BFDDown): "BFDDown",
uint8(BFDInit): "BFDInit",
uint8(BFDUp): "BFDUp",
}

const (
BFDMinSysTXIntervalUs = 100000
BFDDflSysTXIntervalUs = 200000
@@ -109,17 +119,24 @@ func (bs *Struct) BFDAddRemote(args ConfigArgs, cbs Notifer) error {

sess := bs.BFDSessMap[args.RemoteIP]
if sess != nil {
var update bool
if sess.Instance == args.Instance {
if sess.DesMinTxInt != args.Interval {
if args.Interval != 0 && sess.DesMinTxInt != args.Interval {
sess.DesMinTxInt = args.Interval
sess.ReqMinRxInt = args.Interval
sess.ReqMinEchoInt = args.Interval
update = true
}
if args.Multi != 0 && sess.MyMulti != args.Multi {
sess.MyMulti = args.Multi
update = true
}
if update {
sess.Fin <- true
sess.TxTicker.Stop()
sess.RxTicker.Stop()
sess.State = BFDDown

sess.DesMinTxInt = args.Interval
sess.ReqMinRxInt = args.Interval
sess.ReqMinEchoInt = args.Interval

sess.TxTicker = time.NewTicker(time.Duration(sess.DesMinTxInt) * time.Microsecond)
sess.RxTicker = time.NewTicker(time.Duration(BFDMinSysRXIntervalUs) * time.Microsecond)
go sess.bfdSessionTicker()
@@ -137,6 +154,7 @@ func (bs *Struct) BFDAddRemote(args ConfigArgs, cbs Notifer) error {
sess = new(bfdSession)
sess.Instance = args.Instance
sess.Notify = cbs

err := sess.initialize(args.RemoteIP, args.SourceIP, args.Port, args.Interval, args.Multi)
if err != nil {
return errors.New("bfd failed to init session")
@@ -162,6 +180,29 @@ func (bs *Struct) BFDDeleteRemote(args ConfigArgs) error {
return nil
}

func (bs *Struct) BFDGet() ([]cmn.BFDMod, error) {
var res []cmn.BFDMod

bs.BFDMtx.Lock()
defer bs.BFDMtx.Unlock()

for _, s := range bs.BFDSessMap {
var temp cmn.BFDMod
pair := strings.Split(s.RemoteName, ":")
temp.Instance = s.Instance
temp.RemoteIP = net.ParseIP(pair[0])
temp.SourceIP = tk.NltoIP(s.MyDisc)
port, _ := strconv.Atoi(pair[1])
temp.Port = uint16(port)
temp.Interval = uint64(s.DesMinTxInt)
temp.RetryCount = s.MyMulti
temp.State = BFDStateMap[uint8(s.State)]
res = append(res, temp)
}

return res, nil
}

func decodeCtrlPacket(buf []byte, size int) *WireRaw {

if size < 24 {