// destinations returns a list of destinations that are currently // configured in the kernel IPVS table for the specified service. func destinations(svc *Service) ([]*Destination, error) { msg, err := netlink.NewMessage(C.IPVS_CMD_GET_DEST, family, netlink.MFDump) if err != nil { return nil, err } defer msg.Free() ic := &ipvsCommand{Service: newIPVSService(svc)} if err := msg.Marshal(ic); err != nil { return nil, err } var dsts []*Destination cb := func(msg *netlink.Message, arg interface{}) error { ic := &ipvsCommand{} if err := msg.Unmarshal(ic); err != nil { return fmt.Errorf("failed to unmarshal service: %v", err) } if ic.Destination == nil { return errors.New("no destination in unmarshalled message") } dsts = append(dsts, ic.Destination.toDestination()) return nil } if err := msg.SendCallback(cb, nil); err != nil { return nil, err } return dsts, nil }
// services returns a list of services that are currently configured in the // kernel IPVS table. If a specific service is given, an exact match will be // attempted and a single service will be returned if it is found. func services(svc *Service) ([]*Service, error) { var flags int if svc == nil { flags = netlink.MFDump } msg, err := netlink.NewMessage(C.IPVS_CMD_GET_SERVICE, family, flags) if err != nil { return nil, err } defer msg.Free() if svc != nil { ic := &ipvsCommand{Service: newIPVSService(svc)} if err := msg.Marshal(ic); err != nil { return nil, err } } var svcs []*Service cb := func(msg *netlink.Message, arg interface{}) error { ic := &ipvsCommand{} if err := msg.Unmarshal(ic); err != nil { return fmt.Errorf("failed to unmarshal service: %v", err) } if ic.Service == nil { return errors.New("no service in unmarshalled message") } svcs = append(svcs, ic.Service.toService()) return nil } if err := msg.SendCallback(cb, nil); err != nil { return nil, err } for _, svc := range svcs { dsts, err := destinations(svc) if err != nil { return nil, err } svc.Destinations = dsts } return svcs, nil }
func TestServiceNetlinkMarshal(t *testing.T) { m, err := netlink.NewMessage(nlTestCommand, nlTestFamily, 0) if err != nil { t.Fatalf("Failed to make netlink message: %v", err) } defer m.Free() ic := &ipvsCommand{Service: testIPVSService} if err := m.Marshal(ic); err != nil { t.Fatalf("Failed to marshal: %v", err) } got, err := m.Bytes() if err != nil { t.Fatalf("Failed to get message bytes: %v", err) } if want := nlmIPVSAddService; !bytes.Equal(got, want) { t.Errorf("Got netlink bytes %#v, want %#v", got, want) } }