Skip to content

Commit

Permalink
dpvs-agent: implementation of ipset api
Browse files Browse the repository at this point in the history
Signed-off-by: ywc689 <[email protected]>
  • Loading branch information
ywc689 committed Aug 22, 2024
1 parent 8be8fa4 commit a18ed1b
Show file tree
Hide file tree
Showing 10 changed files with 1,910 additions and 28 deletions.
55 changes: 31 additions & 24 deletions include/conf/ipset.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,34 +43,36 @@ enum ipset_op {
};

struct ipset_option {
int family;
union {
struct {
bool comment;
int hashsize;
int maxelem;
} create;
int32_t hashsize;
uint32_t maxelem;
uint8_t comment;
} __attribute__((__packed__)) create;
struct {
bool nomatch;
} add;
char padding[8];
uint8_t nomatch;
} __attribute__((__packed__)) add;
};
};
uint8_t family;
} __attribute__((__packed__));

struct ipset_param {
char type[IPSET_MAXNAMELEN];
char name[IPSET_MAXNAMELEN];
char comment[IPSET_MAXCOMLEN];
int opcode;
struct ipset_option option;
uint16_t opcode;
uint16_t flag;
struct ipset_option option;

uint8_t proto;
uint8_t cidr;
struct inet_addr_range range; /* port in host byteorder */
uint8_t mac[6];
char iface[IFNAMSIZ];
uint8_t mac[6];

/* for type with 2 nets */
uint8_t padding;
uint8_t cidr2;
struct inet_addr_range range2;
//uint8_t mac[2];
Expand All @@ -83,43 +85,48 @@ struct ipset_member {
uint8_t cidr;
uint8_t proto;
uint16_t port;
uint8_t mac[6];
char iface[IFNAMSIZ];
bool nomatch;
uint8_t mac[6];
uint8_t nomatch;

/* second net */
union inet_addr addr2;
uint8_t cidr2;
uint16_t port2;
uint8_t padding[2];
union inet_addr addr2;
};

struct ipset_info {
char name[IPSET_MAXNAMELEN];
char type[IPSET_MAXNAMELEN];
bool comment;
uint8_t comment;

uint8_t af;
uint8_t padding[2];

union {
struct ipset_bitmap_header {
struct inet_addr_range range;
uint8_t cidr;
uint8_t padding[3];
struct inet_addr_range range;
} bitmap;
struct ipset_hash_header {
int hashsize;
int maxelem;
uint8_t padding[4]; // aligned for dpvs-agent
int32_t hashsize;
uint32_t maxelem;
} hash;
};

int af;
size_t size;
int entries;
int references;
uint32_t size;
uint32_t entries;
uint32_t references;

void *members;
};

struct ipset_info_array {
int nipset;
struct ipset_info infos[0];
uint32_t nipset;
struct ipset_info infos[0];
} __attribute__((__packed__));

#endif /* __DPVS_IPSET_CONF_H__ */
2 changes: 1 addition & 1 deletion tools/dpip/ipset.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static int
addr_arg_parse(char *arg, struct inet_addr_range *range, uint8_t *cidr)
{
char *ip1, *ip2, *sep;
int *af = &param.option.family;
uint8_t *af = &param.option.family;

/* ip/cidr */
if (cidr && (sep = strstr(arg, "/"))) {
Expand Down
14 changes: 14 additions & 0 deletions tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
rotatelogs "github.com/lestrrat-go/file-rotatelogs"

"github.com/dpvs-agent/cmd/device"
"github.com/dpvs-agent/cmd/ipset"
"github.com/dpvs-agent/cmd/ipvs"
"github.com/dpvs-agent/pkg/ipc/pool"
"github.com/dpvs-agent/pkg/settings"
Expand Down Expand Up @@ -187,6 +188,8 @@ func (agent *DpvsAgentServer) instantiateAPI(restAPI *operations.DpvsAgentAPI) {

logger := hclog.Default().Named("main")

//////////////////////////////////// ipvs ///////////////////////////////////////////

// delete
restAPI.VirtualserverDeleteVsVipPortHandler = ipvs.NewDelVsItem(cp, logger)
restAPI.VirtualserverDeleteVsVipPortLaddrHandler = ipvs.NewDelVsLaddr(cp, logger)
Expand All @@ -210,6 +213,8 @@ func (agent *DpvsAgentServer) instantiateAPI(restAPI *operations.DpvsAgentAPI) {
// post
restAPI.VirtualserverPostVsVipPortRsHandler = ipvs.NewPostVsRs(cp, logger)

//////////////////////////////////// device ///////////////////////////////////////////

// get
// restAPI.DeviceGetDeviceNameAddrHandler
// restAPI.DeviceGetDeviceNameRouteHandler
Expand All @@ -230,6 +235,15 @@ func (agent *DpvsAgentServer) instantiateAPI(restAPI *operations.DpvsAgentAPI) {
restAPI.DeviceDeleteDeviceNameVlanHandler = device.NewDelDeviceVlan(cp, logger)
restAPI.DeviceDeleteDeviceNameNetlinkAddrHandler = device.NewDelDeviceNetlinkAddr(cp, logger)

//////////////////////////////////// ipset ///////////////////////////////////////////

// GET
restAPI.IpsetGetHandler = ipset.NewIpsetGet(cp, logger)
restAPI.IpsetGetAllHandler = ipset.NewIpsetGetAll(cp, logger)

// POST
restAPI.IpsetIsInHandler = ipset.NewIpsetIsIn(cp, logger)

switch strings.ToLower(agent.InitMode) {
case "network":
case "local":
Expand Down
63 changes: 63 additions & 0 deletions tools/dpvs-agent/cmd/ipset/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2023 IQiYi Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ipset

import (
"github.com/dpvs-agent/pkg/ipc/pool"
"github.com/dpvs-agent/pkg/ipc/types"
api "github.com/dpvs-agent/restapi/operations/ipset"
"github.com/go-openapi/runtime/middleware"
"github.com/hashicorp/go-hclog"
)

type ipsetGet struct {
connPool *pool.ConnPool
logger hclog.Logger
}

func NewIpsetGet(cp *pool.ConnPool, parentLogger hclog.Logger) *ipsetGet {
logger := hclog.Default()
if parentLogger != nil {
logger = parentLogger.Named("ipsetGet")
}
return &ipsetGet{connPool: cp, logger: logger}
}

func (h *ipsetGet) Handle(params api.GetParams) middleware.Responder {
conf := &types.IPSetParam{}

conf.SetOpcode(types.IPSET_OP_LIST)
conf.SetName(params.Name)
infos, err, derr := conf.Get(h.connPool, h.logger)
if err != nil {
h.logger.Error("Ipset Get failed.", "setName", params.Name, "Reason", err.Error())
if derr == types.EDPVS_NOTEXIST {
return api.NewGetNotFound().WithPayload(derr.String())
}
return api.NewGetFailure().WithPayload(err.Error())
}

h.logger.Info("Ipset Get succeed", "setName", params.Name)
model, err := infos.Model()
if err != nil {
h.logger.Error("Modelling ipset Get result failed.", "setName", params.Name, "Reason", err.Error())
}

resp := api.NewGetOK()
if model.Count > 0 {
resp.SetPayload(model.Infos[0])
}
return resp
}
54 changes: 54 additions & 0 deletions tools/dpvs-agent/cmd/ipset/get_all.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2023 IQiYi Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ipset

import (
"github.com/dpvs-agent/pkg/ipc/pool"
"github.com/dpvs-agent/pkg/ipc/types"
api "github.com/dpvs-agent/restapi/operations/ipset"
"github.com/go-openapi/runtime/middleware"
"github.com/hashicorp/go-hclog"
)

type ipsetGetAll struct {
connPool *pool.ConnPool
logger hclog.Logger
}

func NewIpsetGetAll(cp *pool.ConnPool, parentLogger hclog.Logger) *ipsetGetAll {
logger := hclog.Default()
if parentLogger != nil {
logger = parentLogger.Named("ipsetGetAll")
}
return &ipsetGetAll{connPool: cp, logger: logger}
}

func (h *ipsetGetAll) Handle(params api.GetAllParams) middleware.Responder {
conf := &types.IPSetParam{}

conf.SetOpcode(types.IPSET_OP_LIST)
infos, err, _ := conf.Get(h.connPool, h.logger)
if err != nil {
h.logger.Error("Ipset GetAll failed.", "Reason", err.Error())
return api.NewGetAllFailure().WithPayload(err.Error())
}

h.logger.Info("Ipset GetAll succeed")
model, err := infos.Model()
if err != nil {
h.logger.Error("Modelling ipset GetAll result failed.", "Reason", err.Error())
}
return api.NewGetAllOK().WithPayload(model)
}
81 changes: 81 additions & 0 deletions tools/dpvs-agent/cmd/ipset/is_in.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2023 IQiYi Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ipset

import (
"fmt"

"github.com/dpvs-agent/pkg/ipc/pool"
"github.com/dpvs-agent/pkg/ipc/types"
api "github.com/dpvs-agent/restapi/operations/ipset"
"github.com/go-openapi/runtime/middleware"
"github.com/hashicorp/go-hclog"
)

type ipsetIsIn struct {
connPool *pool.ConnPool
logger hclog.Logger
}

func NewIpsetIsIn(cp *pool.ConnPool, parentLogger hclog.Logger) *ipsetIsIn {
logger := hclog.Default()
if parentLogger != nil {
logger = parentLogger.Named("ipsetIsIn")
}
return &ipsetIsIn{connPool: cp, logger: logger}
}

func (h *ipsetIsIn) Handle(params api.IsInParams) middleware.Responder {
if params.IpsetCell == nil {
return api.NewIsInBadRequest().WithPayload("missing ipset entry")
}

conf := types.IPSetParam{}
conf.SetOpcode(types.IPSET_OP_TEST)
conf.SetName(params.Name)
conf.SetKind(string(*params.IpsetCell.Type))
if err := conf.BuildMember(params.IpsetCell.Member); err != nil {
return api.NewIsInBadRequest().WithPayload(fmt.Sprintf("invalid member: %s", err.Error()))
}

if err := conf.Check(); err != nil {
return api.NewIsInBadRequest().WithPayload(fmt.Sprintf("invalid param: %s", err.Error()))
}

result, err, derr := conf.IsIn(h.connPool, h.logger)
if err != nil {
h.logger.Error("Ipset IsIn failed.", "setName", params.Name, "Reason", err.Error())
if derr == types.EDPVS_NOTEXIST {
return api.NewIsInNotFound().WithPayload(derr.String())
}
return api.NewIsInFailure().WithPayload(err.Error())
}
h.logger.Info("Ipset InIn succeed.", "setName", params.Name)

nomatch := ""
if params.IpsetCell.Member.Options != nil &&
params.IpsetCell.Member.Options.NoMatch != nil &&
*params.IpsetCell.Member.Options.NoMatch {
nomatch = " (nomatch)"
}

msg := ""
if result {
msg = fmt.Sprintf("%s%s is IN set %s", nomatch, *params.IpsetCell.Member.Entry, params.Name)
} else {
msg = fmt.Sprintf("%s%s is NOT IN set %s", nomatch, *params.IpsetCell.Member.Entry, params.Name)
}
return api.NewIsInOK().WithPayload(&api.IsInOKBody{Result: &result, Message: msg})
}
3 changes: 0 additions & 3 deletions tools/dpvs-agent/pkg/ipc/types/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ import (
"github.com/dpvs-agent/pkg/ipc/pool"
)

/* derived from: include/conf/ipset.h */
const IPSET_MAXNAMELEN = 32

/*
derived from:
- include/conf/blklst.h
Expand Down
5 changes: 5 additions & 0 deletions tools/dpvs-agent/pkg/ipc/types/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ const (
SOCKOPT_SET_IFADDR_SET
SOCKOPT_SET_IFADDR_FLUSH
SOCKOPT_GET_IFADDR_SHOW
SOCKOPT_GET_IFMADDR_SHOW

SOCKOPT_NETIF_SET_LCORE
SOCKOPT_NETIF_SET_PORT
Expand All @@ -255,8 +256,12 @@ const (
SOCKOPT_NETIF_GET_PORT_XSTATS
SOCKOPT_NETIF_GET_PORT_EXT_INFO
SOCKOPT_NETIF_GET_BOND_STATUS
SOCKOPT_NETIF_GET_MADDR
SOCKOPT_NETIF_GET_MAX

SOCKOPT_SET_LLDP_TODO
SOCKOPT_GET_LLDP_SHOW

SOCKOPT_SET_NEIGH_ADD
SOCKOPT_SET_NEIGH_DEL
SOCKOPT_GET_NEIGH_SHOW
Expand Down
Loading

0 comments on commit a18ed1b

Please sign in to comment.