The Junosphere Experience, Part Three – Topology Files

In the previous article, I briefly mentioned that Junosphere users can load their own topology files. In this article, I will explain some basics of these files.

When I started using Junosphere, I needed a network that would make sense to me. I had a perfect candidate, since I am in the middle of the OSPF database exploration on Junos and I have already built a topology for my homebrew lab. Here’s what I have emulated at home.

Junos OSPF Diagram

I wanted to replicate the exact same thing in Junosphere, so I can continue working on the same project.

Junosphere topologies have few requirements:

  • Files must be gzipped, tar archives with the extenstion of “tgz”.
  • Topology definition file must be called “topology.vmm” and placed at the top-level folder of the topology archive file.
  • Individual device configurations must be in a subfolder called “configset” in the same archive.

The “topology.vmm” file has a format very similar in look and feel to Junos configuration files. It is, of course not Junos configuration. Here’s the example configuration for the network I ended up using. First of all, let’s take a look at the modified diagram.

Junosphere OSPF Diagram

The only thing changed on the diagram are interface names, as well as added “privateX” identifiers. I will explain these in a bit, but before I do that, let’s take a look at the working VMM file.

#include "common.defs"

config "config" {

vm "R1" {
   hostname "R1" ;
   VJX1000_LATEST

   interface "em0" { EXTERNAL; };          /* ge-0/0/0 */
   interface "em1" { bridge "private0"; }; /* ge-0/0/1 */
   interface "em2" { bridge "private1"; }; /* ge-0/0/2 */

   install "ENV(HOME)/active/configset/R1.conf" "/root/junos.conf";
};

vm "R2" {
   hostname "R2" ;
   VJX1000_LATEST

   interface "em0" { EXTERNAL; };          /* ge-0/0/0 */
   interface "em1" { bridge "private2"; }; /* ge-0/0/1 */

   install "ENV(HOME)/active/configset/R2.conf" "/root/junos.conf";
};

vm "R3" {
   hostname "R3" ;
   VJX1000_LATEST

   interface "em0" { EXTERNAL; };          /* ge-0/0/0 */
   interface "em1" { bridge "private2"; }; /* ge-0/0/1 */
   interface "em2" { bridge "private1"; }; /* ge-0/0/2 */

   install "ENV(HOME)/active/configset/R3.conf" "/root/junos.conf";
};

vm "R4" {
   hostname "R4" ;
   VJX1000_LATEST

   interface "em0" { EXTERNAL; };          /* ge-0/0/0 */
   interface "em1" { bridge "private0"; }; /* ge-0/0/1 */

   install "ENV(HOME)/active/configset/R4.conf" "/root/junos.conf";
};

PRIVATE_BRIDGES

};

That doesn’t look too complicated, but it does have few important components. The very first part includes some common definitions into your configuration. These definitions are things like variable names to reference working Junos images, defined interconnections (bridges), etc.

After this first part, we need to define the actual topology configuration. This is what the “config” section is all about. Inside this section, we define all individual routers. I showed only minimal router definitions, where I defined host names, Junos image to run (variable called VJX1000_LATEST), interfaces and the “install” line, which specifes which configuration file from the “configset” folder to load as the active configuration on the router.

Finally, at the end, we call a variable “PRIVATE_BRIDGES”, which defines the interconnections.

Now, let’s go back and take a look at one of the routers.

vm "R1" {
   hostname "R1" ;
   VJX1000_LATEST

   interface "em0" { EXTERNAL; };          /* ge-0/0/0 */
   interface "em1" { bridge "private0"; }; /* ge-0/0/1 */
   interface "em2" { bridge "private1"; }; /* ge-0/0/2 */

   install "ENV(HOME)/active/configset/R1.conf" "/root/junos.conf";
};

it’s important to notice that interfaces in the VMM configuration are called emX, but they will directly translate to ge-0/0/X in the running VM. Also, em0 interface cannot be used for interconnections, as it is reserved as a pre-defined management interface. Junosphere will configure the IP address on it and you can use it to SSH/Telnet into your VM router.

Even if you opt to install your own configuration file, much more will be generated for you in the active configuration. Here’s the sample of my configured R2 and the resulting config on Junosphere.

My Configuration:

system {
   host-name R2;
   time-zone PST8PDT;
   root-authentication {
      encrypted-password [...];
   }
   login {
      user markom {
         uid 2000;
         class super-user;
         authentication {
            encrypted-password [...];
         }
      }
   }
   syslog {
      user * {
         any emergency;
      }
      file messages {
         any notice;
         authorization info;
      }
      file interactive-commands {
         interactive-commands any;
      }
   }      
}
interfaces {
    ge-0/0/1 {
        unit 0 {
            family inet {
                address 192.168.23.2/24;
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 192.168.0.2/32;
            }
        }
    }
}
routing-options {
    router-id 2.2.2.2;
}
protocols {
    ospf {
        area 0.0.0.23 {
            interface ge-0/0/1.0 {
                interface-type p2p;
            }
        }
    }
}

Resulting Configuration on Junosphere:

version 10.3D0;
groups {
    member0 {
        system {
            host-name R2;
        }
    }
    global {
        system {
            time-zone America/Los_Angeles;
            debugger-on-panic;
            debugger-on-break;
            dump-on-panic;
            root-authentication {
                encrypted-password [...]; ## SECRET-DATA
            }
            name-server {
                8.8.8.8;
            }
            login {                     
                message "Welcome to the cloudnpassword is [...]n";
                user juniper {
                    uid 2000;
                    class super-user;
                    authentication {
                        encrypted-password [...]; ## SECRET-DATA
                    }
                }
            }
            services {
                finger;
                ftp;
                rlogin;
                rsh;
                ssh;
                telnet;
                xnm-clear-text;
            }
            syslog {
                host log {
                    kernel info;
                    any notice;         
                    pfe info;
                    interactive-commands any;
                }
                file messages {
                    kernel info;
                    any notice;
                    authorization info;
                    pfe info;
                    archive world-readable;
                }
                file security {
                    interactive-commands any;
                    archive world-readable;
                }
            }
            archival {
                configuration {
                    transfer-on-commit;
                    archive-sites {
                        "ftp://tftp:tftp@10.233.255.254/active/configset";
                    }
                }
            }                           
            processes {
                routing enable;
                management enable;
                watchdog enable;
                snmp enable;
                inet-process enable;
                mib-process enable;
            }
        }
        chassis {
            dump-on-panic;
        }
        security {
            forwarding-options {
                family {
                    inet6 {
                        mode packet-based;
                    }
                    mpls {
                        mode packet-based;
                    }
                    iso {
                        mode packet-based;
                    }
                }
            }
        }
    }
}
apply-groups [ global member0 ];
system {
    host-name R2;
    time-zone PST8PDT;
    root-authentication {
        encrypted-password [...]; ## SECRET-DATA
        ssh-rsa "ssh-rsa [...]; ## SECRET-DATA
    }
    login {
        user markom {
            uid 2000;
            class super-user;           
            authentication {
                encrypted-password [...]; ## SECRET-DATA
            }
        }
    }
    syslog {
        user * {
            any emergency;
        }
        file messages {
            any notice;
            authorization info;
        }
        file interactive-commands {
            interactive-commands any;
        }
    }
}
interfaces {
    ge-0/0/0 {
        unit 0 {
            family inet {               
                address 10.233.248.24/20;
            }
        }
    }
    ge-0/0/1 {
        unit 0 {
            family inet {
                address 192.168.23.2/24;
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 192.168.0.2/32;
            }
        }
    }
}
routing-options {
    router-id 2.2.2.2;
}
protocols {                             
    ospf {
        area 0.0.0.23 {
            interface ge-0/0/1.0 {
                interface-type p2p;
            }
        }
    }
}

One of the first things I did when I accessed one of my routers was to load the factory defaults using “load factory-default”. In my experience, this will tear down any interconnections between VMs and the only way to fix it is to restart your topology.

While this additional configuration is somewhat annoying, especially when trying to make baby steps in Junos, there may be a way to get around it. It would certainly be very nice of Juniper to correct the behavior of interconnections and I’m sure that will come at a later date.

UPDATE
I found a fix/workaround for this problem. Adding the following configuration fixes the issue.

security {
    forwarding-options {
        family {
            mpls {
                mode packet-based;
            }                           
        }
    }
}

Thanks to Chris Jones for the history lesson as to why.

The last thing I should mention are “bridges”. Think of bridges as “inter-VM VLANs”. These are private virtual connections between emulated VM interfaces that make up the virtual cables. You can define them yourself using “bridges” syntax (explained in the provided documentation), or you can simply use the pre-defined ones from “PRIVATE_BRIDGES”. There are several of interest.

  • Bridge “dead” simply means an unused interface. Interfaces must be specified in order, i.e. em0, em1, em2, em3, etc. If some of the interfaces are not used by your topology, you should connect them to “dead” bridge.
  • Bridge “EXTERNAL” connects the interface to an external (Junosphere) network. You want to use this bridge with em0.
  • Bridges PrivateN can be used to interconnect your VMs.

There are couple more things you can do with the VMM file, but this will get you going in no time.

She’s looking worried, as I spent all morning playing around with this. I leave for two weeks tomorrow and She wants me to spend more time with her. Bad timing for Junosphere to start working!

  1. Could you please explain me why would you have to set interface-type p2p for gigabit ethernet interface, or why is interface-type p2p used for serial interface for example?

    Pozdrav :)

  2. The fix does work. Care to share the history lesson?

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>