-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7407bd0
commit 037fedd
Showing
12 changed files
with
654 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
p4rt-client | ||
.idea/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package lib | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"golang.org/x/net/context" | ||
p4 "github.com/p4lang/p4runtime/go/p4/v1" | ||
"google.golang.org/genproto/googleapis/rpc/code" | ||
) | ||
type P4rtClient struct { | ||
Client p4.P4RuntimeClient | ||
Stream p4.P4Runtime_StreamChannelClient | ||
DeviceId uint64 | ||
ElectionId *p4.Uint128 | ||
} | ||
|
||
|
||
func Init(c *P4rtClient) (err error) { | ||
// Initialize stream for mastership and packet I/O | ||
log.Println("INIT") | ||
c.Stream, err = c.Client.StreamChannel(context.Background()) | ||
if err != nil { | ||
log.Fatalf("Error creating StreamChannel %v\n",err) | ||
} | ||
log.Printf("In INIT deviceId is %d\n",c.DeviceId) | ||
go func() { | ||
for { | ||
res, err := c.Stream.Recv() | ||
if err != nil { | ||
log.Fatalf("stream recv error: %v\n", err) | ||
} else if arb := res.GetArbitration(); arb != nil { | ||
if code.Code(arb.Status.Code) == code.Code_OK { | ||
log.Println("client is master") | ||
} else { | ||
log.Println("client is not master") | ||
} | ||
} else { | ||
fmt.Printf("stream recv: %v\n", res) | ||
} | ||
} | ||
}() | ||
return | ||
} | ||
func (c *P4rtClient) SetMastership(electionId *p4.Uint128) (err error) { | ||
c.ElectionId = electionId | ||
mastershipReq := &p4.StreamMessageRequest{ | ||
Update: &p4.StreamMessageRequest_Arbitration{ | ||
Arbitration: &p4.MasterArbitrationUpdate{ | ||
DeviceId: c.DeviceId, | ||
ElectionId: electionId, | ||
}, | ||
}, | ||
} | ||
err = c.Stream.Send(mastershipReq) | ||
return | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package lib | ||
|
||
import ( | ||
"crypto/md5" | ||
"encoding/binary" | ||
"github.com/golang/protobuf/proto" | ||
p4 "github.com/p4lang/p4runtime/go/p4/v1" | ||
"io/ioutil" | ||
"log" | ||
p4config "github.com/p4lang/p4runtime/go/p4/config/v1" | ||
"context" | ||
) | ||
|
||
func PushP4Info(client *P4rtClient,p4infoFilename *string)error{ | ||
p4info,err := loadP4Info(p4infoFilename) | ||
if err != nil{ | ||
return err | ||
} | ||
deviceConfig:=[]byte{} | ||
hash := md5.Sum(deviceConfig) | ||
cookie := binary.LittleEndian.Uint64(hash[:]) | ||
|
||
config := &p4.ForwardingPipelineConfig{ | ||
P4Info: &p4info, | ||
P4DeviceConfig: deviceConfig, | ||
Cookie: &p4.ForwardingPipelineConfig_Cookie{Cookie: cookie}, | ||
} | ||
|
||
req := &p4.SetForwardingPipelineConfigRequest{ | ||
DeviceId: client.DeviceId, | ||
RoleId: 0, // not used | ||
ElectionId: client.ElectionId, | ||
Action: p4.SetForwardingPipelineConfigRequest_VERIFY_AND_COMMIT, | ||
Config: config, | ||
} | ||
_,err = client.Client.SetForwardingPipelineConfig(context.Background(), req) | ||
return err | ||
} | ||
func loadP4Info(p4infoPath *string) (p4info p4config.P4Info, err error) { | ||
log.Printf("P4 Info: %s\n", p4infoPath) | ||
|
||
p4infoBytes, err := ioutil.ReadFile(*p4infoPath) | ||
if err != nil { | ||
return | ||
} | ||
err = proto.UnmarshalText(string(p4infoBytes), &p4info) | ||
return | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package models | ||
|
||
type IPv4Config struct { | ||
VrfId *string | ||
DestinationCIDR *string | ||
NexthopId *string | ||
IPv4TableId uint32 | ||
SetNexthopId uint32 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package models | ||
|
||
//func RounterTableInsert(outerInterfaceTableId uint32,routerIntId string,routerIntPortId uint32,routerInterMAC string,setMacAndPort uint32){ | ||
|
||
|
||
type L3Config struct{ | ||
RouterInterfaceTableId uint32 | ||
RouterInterfaceId *string | ||
EgressPort uint32 | ||
RouterInterfacePortId uint32 | ||
RouterInterfaceMAC *string | ||
SetMacAndPortId uint32 | ||
} | ||
func (l3config *L3Config)String()string{ | ||
return "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package models | ||
|
||
|
||
type NeighborConfig struct{ | ||
RouterInterfaceId *string | ||
NeighborIP *string | ||
DestinationMac *string | ||
NeighborTableId uint32 | ||
NeighborTableActionId uint32 | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package models | ||
|
||
type NexthopConfig struct { | ||
NexthopTableId uint32 | ||
NexthopId *string | ||
SetNexthopId uint32 | ||
RouterInterfaceId *string | ||
NeighborIp *string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
p4 "github.com/p4lang/p4runtime/go/p4/v1" | ||
"github.com/pins/p4rt-client/internal/lib" | ||
"github.com/pins/p4rt-client/internal/models" | ||
"github.com/pins/p4rt-client/tables" | ||
"golang.org/x/net/context" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials" | ||
"log" | ||
) | ||
|
||
// Authentication holds the login/password | ||
type Authentication struct { | ||
Login string | ||
Password string | ||
// RequireTransportSecurity indicates whether the credentials requires transport security | ||
} | ||
|
||
// GetRequestMetadata gets the current request metadata | ||
func (a *Authentication) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { | ||
return map[string]string{ | ||
"login": a.Login, | ||
"password": a.Password, | ||
}, nil | ||
} | ||
|
||
func (a *Authentication) RequireTransportSecurity() bool { | ||
return true | ||
} | ||
func main() { | ||
useSsl := flag.Bool("ssl", false, "use ssl") | ||
useAuth := flag.Bool("auth", false, "use auth") | ||
serverAddressPort := flag.String("server", "", "address and port of p4rt server on swich" ) | ||
fqdn := flag.String("fqdn", "", "FQDN of the service to match what is in server.crt") | ||
crtFile := flag.String("cert", "cert/server.crt", "Public cert for server to establish tls session") | ||
//######################################### | ||
pushP4Info := flag.Bool("pushP4Info",false,"push P4Info text file to switch") | ||
p4info := flag.String("p4info","","p4info text filename which describes p4 application") | ||
|
||
//######################################### | ||
addL3 := flag.Bool("addL3",false,"add entries needed for layer 3 routing") | ||
routerIntTableId :=flag.Uint("routerTable",0,"id for ingress.routing.router_interface_table from p4info.txt") | ||
routerInterfaceId := flag.String("routerInterface","","name to give to router interface") | ||
routerIntPort := flag.Uint("routerPortId",1,"port number to assign to router interface port") | ||
routerIntMAC := flag.String("routerIntMAC","","MAC address to be used for router interface e.g. 00:00:00:11:22:dd") | ||
egressPort := flag.Uint("egressPort",0,"switch port to egress") | ||
setMacPort := flag.Uint("setPortMac",0,"action id associated with action ingress.routing.set_port_and_src_mac ") | ||
nextHopTable := flag.Uint("nextHopTable",0,"table id associated with ingress.routing.nexthop_table from p4info.txt") | ||
nextHopId := flag.String("nextHopId","","name to associate with next hop entry") | ||
nextHopAction := flag.Uint("setNextHopAction",0,"action id associated with ingress.routing.set_nexthop_id from p4info.txt") | ||
neighborIp := flag.String("neighborIp","","ip address of next hop neighbor eg. 10.10.10.2") | ||
destMAC := flag.String("destMAC","","MAC address for neighbor IP e.g. 11:22:33:44:55:66") | ||
neighborTable := flag.Uint("neighborTable",0,"id associated with ingress.routing.neighbor_table from p4info.txt") | ||
setDestMac := flag.Uint("setDestMacAction",0,"id associated with ingress.routing.set_dst_mac from p4info.txt") | ||
vrfId := flag.String("vrf","default","name of vrf to use") | ||
destNetwork := flag.String("routedNetwork","","CIDR of network to route e.g. 1.2.3.4/8") | ||
ipv4Table := flag.Uint("ipv4table",0,"id associated with ingress.routing.ipv4_table from p4info.txt") | ||
setNextHopId := flag.Uint("setNextHop",0,"id associated with action ingress.routing.set_nexthop_id from p4info.txt") | ||
help := flag.Bool("help",false,"print usage help") | ||
|
||
flag.Parse() | ||
|
||
|
||
if *help{ | ||
basicUsage() | ||
return | ||
} | ||
if *pushP4Info&&*addL3{ | ||
basicUsage() | ||
return | ||
} | ||
|
||
|
||
if *pushP4Info{ | ||
if *p4info==""||*serverAddressPort==""{ | ||
pushP4infoUsage() | ||
return | ||
} | ||
}else if *addL3 { | ||
//sanitiy check | ||
if *routerIntTableId == 0 || *routerInterfaceId == "" || *routerIntMAC == "" || *setMacPort == 0 || *nextHopTable == 0 || *nextHopId == "" || *nextHopAction == 0 || | ||
*egressPort==0||*neighborIp == "" || *destMAC == "" || *vrfId == "" || *destNetwork == "" || *ipv4Table == 0 || *setNextHopId == 0 || *serverAddressPort=="" { | ||
addL3Usage() | ||
return | ||
} | ||
}else{ | ||
basicUsage() | ||
return | ||
} | ||
|
||
var conn *grpc.ClientConn | ||
var err error | ||
auth := Authentication{ | ||
Login: "admin", | ||
Password: "admin", | ||
} | ||
if *useSsl && *useAuth { | ||
|
||
creds, err := credentials.NewClientTLSFromFile(*crtFile, *fqdn) | ||
conn, err = grpc.Dial(*serverAddressPort, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&auth)) | ||
if err != nil { | ||
log.Fatalf("could not load tls cert: %s", err) | ||
} | ||
} else if *useSsl { | ||
creds, err := credentials.NewClientTLSFromFile("cert/server.crt", *fqdn) | ||
conn, err = grpc.Dial(*serverAddressPort, grpc.WithTransportCredentials(creds)) | ||
if err != nil { | ||
log.Fatalf("could not load tls cert: %s", err) | ||
} | ||
} else if *useAuth { | ||
conn, err = grpc.Dial(*serverAddressPort, grpc.WithInsecure(), grpc.WithPerRPCCredentials(&auth)) | ||
} else { | ||
|
||
log.Println(*serverAddressPort) | ||
conn, err = grpc.Dial(*serverAddressPort, grpc.WithInsecure()) | ||
if err != nil { | ||
log.Fatalf("Failed to dial switch: %s", err) | ||
} | ||
} | ||
|
||
defer conn.Close() | ||
client := p4.NewP4RuntimeClient(conn) | ||
p4client:=&lib.P4rtClient{ | ||
Client:client, | ||
DeviceId:uint64(183807201), | ||
} | ||
lib.Init(p4client) | ||
if *addL3{ | ||
p4client.SetMastership(&p4.Uint128{High: 0, Low: 1}) | ||
l3Config := &models.L3Config{ | ||
RouterInterfaceTableId: uint32(*routerIntTableId), | ||
RouterInterfaceId: routerInterfaceId, | ||
EgressPort: uint32(*egressPort), | ||
RouterInterfacePortId: uint32(*routerIntPort), | ||
RouterInterfaceMAC: routerIntMAC, | ||
SetMacAndPortId: uint32(*setMacPort), | ||
} | ||
tables.RounterTableInsert(p4client,l3Config) | ||
neighborConfig := &models.NeighborConfig{ | ||
RouterInterfaceId: routerInterfaceId, | ||
NeighborIP: neighborIp, | ||
DestinationMac: destMAC, | ||
NeighborTableId: uint32(*neighborTable), | ||
NeighborTableActionId: uint32(*setDestMac), | ||
} | ||
tables.NeighborTableInsert(p4client,neighborConfig) | ||
nexthopConfig := &models.NexthopConfig{ | ||
NexthopTableId:uint32(*nextHopTable), | ||
NexthopId: nextHopId, | ||
SetNexthopId: uint32(*setNextHopId), | ||
RouterInterfaceId: routerInterfaceId, | ||
NeighborIp: neighborIp, | ||
} | ||
tables.NextHopTableInsert(p4client,nexthopConfig) | ||
ipv4Config := &models.IPv4Config{ | ||
VrfId: vrfId, | ||
DestinationCIDR: destNetwork, | ||
NexthopId: nextHopId, | ||
IPv4TableId: uint32(*ipv4Table), | ||
SetNexthopId: uint32(*setNextHopId), | ||
} | ||
tables.Ipv4TableInsert(p4client,ipv4Config) | ||
} | ||
} | ||
func basicUsage(){ | ||
log.Println("p4rt-client can communication with p4runtime on a sonic based switch") | ||
log.Println("\n\nTo Set the p4info file:") | ||
pushP4infoUsage() | ||
log.Println("\n\nTo Configure Layer 3 routing:") | ||
addL3Usage() | ||
log.Println("\n\nTo see more help on arguments:\n./p4rt-client -h") | ||
} | ||
func addL3Usage(){ | ||
usage:= ` | ||
Usage: | ||
./p4rt-client -addL3 \ | ||
-server=$P4RT_LISTEN_ADDRESS \ | ||
-routerTable=$ROUTER_TABLE_ID \ | ||
-routerInterface=$ROUTER_INTERFACE_NAME \ | ||
-routerPortId=$ROUTER_PORT_ID \ | ||
-routerIntMAC=$ROUTER_INTERFACE_MAC_ADDR \ | ||
-setPortMac=$SET_PORT_MAC_ACTION \ | ||
-nextHopTable=$NEXT_HOP_TABLE \ | ||
-nextHopId=$NEXT_HOP_NAME \ | ||
-setNextHopAction=$NEXT_HOP_ACTION_ID \ | ||
-neighborIp=$NEIGHBOR_IP \ | ||
-destMAC=$DEST_MAC \ | ||
-neighborTable=$NEIGHBOR_TABLE_ID \ | ||
-setDestMacAction=$SET_DST_MAC_ACTION_ID \ | ||
-vrf=$VRF_NAME \ | ||
-routedNetwork=$ROUTED_NETWORK_CIDR \ | ||
-ipv4table=$IPV_TABLE_ID \ | ||
-setNextHop=$SET_NEXT_HOP_ACTION_ID` | ||
log.Println(usage) | ||
} | ||
|
||
func pushP4infoUsage(){ | ||
usage:=` | ||
Usage: | ||
./p4rt-client -pushP4info -p4info=$P4_INFO_FILENAME` | ||
log.Println(usage) | ||
} |
Oops, something went wrong.