From d92f5fd847c606ac312ef012e515a403c8e4cf48 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Sun, 9 Aug 2020 18:04:30 -0300 Subject: [PATCH] doc: initial documentation for gRPC Give the FRR users some examples of gRPC usage in scripts to let them start experimenting with the new configuration interface provided by YANG/northbound. Signed-off-by: Rafael Zalamena --- doc/developer/grpc.rst | 249 ++++++++++++++++++++++++++++++++++++++++ doc/developer/index.rst | 1 + doc/developer/subdir.am | 1 + doc/user/grpc.rst | 66 +++++++++++ doc/user/index.rst | 1 + doc/user/subdir.am | 1 + 6 files changed, 319 insertions(+) create mode 100644 doc/developer/grpc.rst create mode 100644 doc/user/grpc.rst diff --git a/doc/developer/grpc.rst b/doc/developer/grpc.rst new file mode 100644 index 0000000000..8029a08b73 --- /dev/null +++ b/doc/developer/grpc.rst @@ -0,0 +1,249 @@ +.. _grpc-dev: + +*************** +Northbound gRPC +*************** + +.. _grpc-languages-bindings: + +Programming Language Bindings +============================= + +The gRPC supported programming language bindings can be found here: +https://grpc.io/docs/languages/ + +After picking a programming language that supports gRPC bindings, the +next step is to generate the FRR northbound bindings. To generate the +northbound bindings you'll need the programming language binding +generator tools and those are language specific. + +Next sections will use Ruby as an example for writing scripts to use +the northbound. + + +.. _grpc-ruby-generate: + +Generating Ruby FRR Bindings +---------------------------- + +Generating FRR northbound bindings for Ruby example: + +:: + + # Install the required gems: + # - grpc: the gem that will talk with FRR's gRPC plugin. + # - grpc-tools: the gem that provides the code generator. + gem install grpc + gem install grpc-tools + + # Create your project/scripts directory: + mkdir /tmp/frr-ruby + + # Go to FRR's grpc directory: + cd grpc + + # Generate the ruby bindings: + grpc_tools_ruby_protoc \ + --ruby_out=/tmp/frr-ruby \ + --grpc_out=/tmp/frr-ruby \ + frr-northbound.proto + + +.. _grpc-ruby-if-sample: + +Using Ruby To Get Interfaces State +---------------------------------- + +Here is a sample script to print all interfaces FRR discovered: + +:: + + require 'frr-northbound_services_pb' + + # Create the connection with FRR's gRPC: + stub = Frr::Northbound::Stub.new('localhost:50051', :this_channel_is_insecure) + + # Create a new state request to get interface state: + request = Frr::GetRequest.new + request.type = :STATE + request.path.push('/frr-interface:lib') + + # Ask FRR. + response = stub.get(request) + + # Print the response. + response.each do |result| + result.data.data.each_line do |line| + puts line + end + end + + +.. note:: + + The generated files will assume that they are in the search path (e.g. + inside gem) so you'll need to either edit it to use ``require_relative`` or + tell Ruby where to look for them. For simplicity we'll use ``-I .`` to tell + it is in the current directory. + + +The previous script will output something like this: + +:: + + $ cd /tmp/frr-ruby + # Add `-I.` so ruby finds the FRR generated file locally. + $ ruby -I. interface.rb + { + "frr-interface:lib": { + "interface": [ + { + "name": "eth0", + "vrf": "default", + "state": { + "if-index": 2, + "mtu": 1500, + "mtu6": 1500, + "speed": 1000, + "metric": 0, + "phy-address": "11:22:33:44:55:66" + }, + "frr-zebra:zebra": { + "state": { + "up-count": 0, + "down-count": 0 + } + } + }, + { + "name": "lo", + "vrf": "default", + "state": { + "if-index": 1, + "mtu": 0, + "mtu6": 65536, + "speed": 0, + "metric": 0, + "phy-address": "00:00:00:00:00:00" + }, + "frr-zebra:zebra": { + "state": { + "up-count": 0, + "down-count": 0 + } + } + } + ] + } + } + + +.. _grpc-ruby-bfd-profile-sample: + +Using Ruby To Create BFD Profiles +--------------------------------- + +In this example you'll learn how to edit configuration using JSON +and programmatic (XPath) format. + +:: + + require 'frr-northbound_services_pb' + + # Create the connection with FRR's gRPC: + stub = Frr::Northbound::Stub.new('localhost:50051', :this_channel_is_insecure) + + # Create a new candidate configuration change. + new_candidate = stub.create_candidate(Frr::CreateCandidateRequest.new) + + # Use JSON to configure. + request = Frr::LoadToCandidateRequest.new + request.candidate_id = new_candidate.candidate_id + request.type = :MERGE + request.config = Frr::DataTree.new + request.config.encoding = :JSON + request.config.data = <<-EOJ + { + "frr-bfdd:bfdd": { + "bfd": { + "profile": [ + { + "name": "test-prof", + "detection-multiplier": 4, + "required-receive-interval": 800000 + } + ] + } + } + } + EOJ + + # Load configuration to candidate. + stub.load_to_candidate(request) + + # Commit candidate. + stub.commit( + Frr::CommitRequest.new( + candidate_id: new_candidate.candidate_id, + phase: :ALL, + comment: 'create test-prof' + ) + ) + + # + # Now lets delete the previous profile and create a new one. + # + + # Create a new candidate configuration change. + new_candidate = stub.create_candidate(Frr::CreateCandidateRequest.new) + + # Edit the configuration candidate. + request = Frr::EditCandidateRequest.new + request.candidate_id = new_candidate.candidate_id + + # Delete previously created profile. + request.delete.push( + Frr::PathValue.new( + path: "/frr-bfdd:bfdd/bfd/profile[name='test-prof']", + ) + ) + + # Add new profile with two configurations. + request.update.push( + Frr::PathValue.new( + path: "/frr-bfdd:bfdd/bfd/profile[name='test-prof-2']/detection-multiplier", + value: 5.to_s + ) + ) + request.update.push( + Frr::PathValue.new( + path: "/frr-bfdd:bfdd/bfd/profile[name='test-prof-2']/desired-transmission-interval", + value: 900_000.to_s + ) + ) + + # Modify the candidate. + stub.edit_candidate(request) + + # Commit the candidate configuration. + stub.commit( + Frr::CommitRequest.new( + candidate_id: new_candidate.candidate_id, + phase: :ALL, + comment: 'replace test-prof with test-prof-2' + ) + ) + + +And here is the new FRR configuration: + +:: + + $ sudo vtysh -c 'show running-config' + ... + bfd + profile test-prof-2 + detect-multiplier 5 + transmit-interval 900 + ! + ! diff --git a/doc/developer/index.rst b/doc/developer/index.rst index 26b590c876..1f803b3772 100644 --- a/doc/developer/index.rst +++ b/doc/developer/index.rst @@ -12,6 +12,7 @@ FRRouting Developer's Guide testing bgpd fpm + grpc ospf zebra vtysh diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am index 6dab244a03..03b4b5a3e2 100644 --- a/doc/developer/subdir.am +++ b/doc/developer/subdir.am @@ -28,6 +28,7 @@ dev_RSTFILES = \ doc/developer/cli.rst \ doc/developer/conf.py \ doc/developer/frr-release-procedure.rst \ + doc/developer/grpc.rst \ doc/developer/hooks.rst \ doc/developer/include-compile.rst \ doc/developer/index.rst \ diff --git a/doc/user/grpc.rst b/doc/user/grpc.rst new file mode 100644 index 0000000000..d6767fc866 --- /dev/null +++ b/doc/user/grpc.rst @@ -0,0 +1,66 @@ +.. _grpc: + +*************** +Northbound gRPC +*************** + +.. program:: configure + +*gRPC* provides a combined front end to all FRR daemons using the YANG +northbound. It is currently disabled by default due its experimental +stage, but it can be enabled with :option:`--enable-grpc` option in the +configure script. + + +.. _grpc-features: + +Northbound gRPC Features +======================== + +* Get/set configuration using JSON/XML/XPath encondings. +* Execute YANG RPC calls. +* Lock/unlock configuration. +* Create/edit/load/update/commit candidate configuration. +* List/get transactions. + + +.. note:: + + There is currently no support for YANG notifications. + + +.. note:: + + You can find more information on how to code programs to interact + with FRR by reading the gRPC Programming Language Bindings section + in the `developer's documentation + `_. + + +.. _grpc-config: + +Daemon gRPC Configuration +========================= + +The *gRPC* module accepts the following run time option: + +- ``port``: the port to listen to (defaults to ``50051``). + + +.. note:: + + At the moment only localhost connections with no SSL/TLS are + supported. + + +To configure FRR daemons to listen to gRPC you need to append the +following parameter to the daemon's command line: ``-M grpc`` +(optionally ``-M grpc:PORT`` to specify listening port). + +To do that in production you need to edit the ``/etc/frr/daemons`` file +so the daemons get started with the command line argument. Example: + +:: + + # other daemons... + bfdd_options=" --daemon -A 127.0.0.1 -M grpc" diff --git a/doc/user/index.rst b/doc/user/index.rst index 7bb86e563b..8ac997f8dd 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -23,6 +23,7 @@ Basics basic vtysh + grpc filter routemap ipv6 diff --git a/doc/user/subdir.am b/doc/user/subdir.am index eb7b7ced52..dd7a193e34 100644 --- a/doc/user/subdir.am +++ b/doc/user/subdir.am @@ -15,6 +15,7 @@ user_RSTFILES = \ doc/user/filter.rst \ doc/user/frr-reload.rst \ doc/user/glossary.rst \ + doc/user/grpc.rst \ doc/user/index.rst \ doc/user/installation.rst \ doc/user/ipv6.rst \ -- 2.39.5