Skip to content

Commit

Permalink
Merge branch 'feature/http'
Browse files Browse the repository at this point in the history
  • Loading branch information
louisroyer committed Feb 14, 2024
2 parents 8eec117 + bddbb3c commit 2b2a49d
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 7 deletions.
7 changes: 6 additions & 1 deletion config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
# pre-exit-hook:
# post-exit-hook:

http-address: "192.0.2.1"
http-port: "8080"
controller-uri: "http://192.0.2.2:8080"
backbone-ip: "fd00::01"

linux-headend-set-source-address: "fd00:51D5:0000::"
ipv4-headend-prefix: "10.0.200.3/32"
headends:
Expand All @@ -21,7 +26,7 @@ headends:
- "fd00:51D5:0000:4::"
source-address-prefix: "fd00:51D5:000:1:9999::/80"
- name: "linux test"
to: "10.0.300.0/24"
to: "10.0.100.0/24"
provider: "Linux"
behavior: "H.Encaps"
policy:
Expand Down
32 changes: 29 additions & 3 deletions internal/app/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ func (s *Setup) AddTasks() {
// 0.2 post-hooks
s.RegisterTask("hook.post", tasks.NewMultiHook(postInitHook, postExitHook))

httpPort := "80" // default http port
if s.config.HTTPPort != nil {
httpPort = *s.config.HTTPPort
}
httpURI := "http://" + s.config.HTTPAddress + httpPort
// 0.3 http server
// 0.4 controller registry
if s.config.Locator != nil {
s.RegisterTask("ctrl.registry", tasks.NewControllerRegistry(s.config.ControllerURI, s.config.BackboneIP, *s.config.Locator, httpURI))
}

// 1. ifaces
// 1.1 iface linux (type dummy)
s.RegisterTask("iproute2.iface.linux", tasks.NewTaskDummyIface(constants.IFACE_LINUX))
Expand Down Expand Up @@ -149,11 +160,18 @@ func (s *Setup) RunExitTask(name string) error {

// Init
func (s *Setup) Init() error {
// 0. user pre-hook
// 0.1. user pre-hook
if err := s.RunInitTask("hook.pre"); err != nil {
return err
}

// 0.2. register into controller
if s.config.Locator != nil {
if err := s.RunInitTask("ctrl.registry"); err != nil {
return err
}
}

// 1. ifaces
// 1.1 iface linux (type dummy)
if err := s.RunInitTask("iproute2.iface.linux"); err != nil {
Expand Down Expand Up @@ -247,10 +265,18 @@ func (s *Setup) Exit() {
// and a maximum of exit tasks must be run,
// even if previous one resulted in errors.

// 0. user pre-hook
// 0.1. user pre-hook
if err := s.RunExitTask("hook.pre"); err != nil {
fmt.Println(err)
}

// 0.2. unregister from controller
if s.config.Locator != nil {
if err := s.RunExitTask("ctrl.registry"); err != nil {
fmt.Println(err)
}
}

// 1. ip rules
// 1.1 rule to rttable nextmn-gtp4
if s.config.GTP4HeadendPrefix != nil {
Expand All @@ -268,7 +294,7 @@ func (s *Setup) Exit() {
// 2 endpoints + headends
// 2. nextmn gtp4 headends
for _, h := range s.config.Headends.FilterWithBehavior(config.ProviderNextMN, config.H_M_GTP4_D) {
t_name := fmt.Sprintf("nextmn.headend/%s", h.Name)
t_name := fmt.Sprintf("nextmn.headend.gtp4/%s", h.Name)
if err := s.RunExitTask(t_name); err != nil {
fmt.Println(err)
}
Expand Down
13 changes: 12 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package config

import (
"io/ioutil"
"net/netip"
"path/filepath"

"gopkg.in/yaml.v3"
Expand All @@ -28,9 +29,19 @@ func ParseConf(file string) (*SRv6Config, error) {
}

type SRv6Config struct {
Debug *bool `yaml:debug,omitempty"`
Debug *bool `yaml:"debug,omitempty"`
Hooks *Hooks `yaml:"hooks"`

// interface with controller
HTTPAddress string `yaml:"http-address"`
HTTPPort *string `yaml:"http-port,omitempty"` // default: 80
// TODO: use a better type for this information
ControllerURI string `yaml:"controller-uri"` // example: http://192.0.2.2/8080

// Backbone IPv6 address
// TODO: use a better type for this information
BackboneIP netip.Addr `yaml:"backbone-ip"`

// headends
LinuxHeadendSetSourceAddress *string `yaml:"linux-headend-set-source-address,omitempty"`
GTP4HeadendPrefix *string `yaml:"ipv4-headend-prefix,omitempty"` // example of prefix: 10.0.0.1/32 (if you use a single IPv4 headend) or 10.0.1.0/24 (with more headends)
Expand Down
95 changes: 95 additions & 0 deletions internal/tasks/controller-registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2023 Louis Royer and the NextMN-SRv6 contributors. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be
// found in the LICENSE file.
// SPDX-License-Identifier: MIT
package tasks

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/netip"
)

// ControllerRegistry registers and unregisters into controller
type ControllerRegistry struct {
WithState
RemoteControlURI string // URI of the controller
LocalControlURI string // URI of the router, used to control it
Locator string
Backbone netip.Addr
Resource string
}

// Create a new ControllerRegistry
func NewControllerRegistry(remoteControlURI string, backbone netip.Addr, locator string, localControlURI string) *ControllerRegistry {
return &ControllerRegistry{
WithState: NewState(),
RemoteControlURI: remoteControlURI,
LocalControlURI: localControlURI,
Locator: locator,
Backbone: backbone,
Resource: "",
}
}

// Init
func (t *ControllerRegistry) RunInit() error {
data := map[string]string{
"locator": t.Locator,
"backbone": t.Backbone.String(),
"control": t.LocalControlURI,
}
json_data, err := json.Marshal(data)
if err != nil {
return err
}
// TODO: retry on timeout failure
resp, err := http.Post(t.RemoteControlURI+"/routers", "application/json", bytes.NewBuffer(json_data))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 400 {
return fmt.Errorf("HTTP Bad request\n")
}
if resp.StatusCode >= 500 {
return fmt.Errorf("HTTP Control Server: internal error\n")
}
if resp.StatusCode == 201 { // created
t.Resource = resp.Header.Get("Location")
}

t.state = true
return nil
}

// Exit
func (t *ControllerRegistry) RunExit() error {
// TODO: retry on timeout failure
// TODO: if Resource has scheme, don't concatenate
if t.Resource == "" {
// nothing to do
t.state = false
return nil
}
req, err := http.NewRequest("DELETE", t.RemoteControlURI+t.Resource, nil)
if err != nil {
return err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 400 {
return fmt.Errorf("HTTP Bad request\n")
}
if resp.StatusCode >= 500 {
return fmt.Errorf("HTTP Control Server: internal error %v\n", resp.Body)
}
t.state = false
return nil
}
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ func main() {
}(ch, setup)
setup.AddTasks()
if err := setup.Run(); err != nil {
fmt.Println("Error while running, exiting…")
log.Fatal(err)
fmt.Println("Error while running, exiting…:", err)
setup.Exit()
os.Exit(2)
}
return nil
Expand Down

0 comments on commit 2b2a49d

Please sign in to comment.