Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

# Copyright (C) 2014,2015 VA Linux Systems Japan K.K. 

# Copyright (C) 2014,2015 YAMAMOTO Takashi <yamamoto at valinux co jp> 

# All Rights Reserved. 

# 

#    Licensed under the Apache License, Version 2.0 (the "License"); you may 

#    not use this file except in compliance with the License. You may obtain 

#    a copy of the License at 

# 

#         http://www.apache.org/licenses/LICENSE-2.0 

# 

#    Unless required by applicable law or agreed to in writing, software 

#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

#    License for the specific language governing permissions and limitations 

#    under the License. 

 

""" 

* references 

** OVS agent https://wiki.openstack.org/wiki/Ovs-flow-logic 

""" 

 

from neutron.plugins.common import constants as p_const 

from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants 

from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl \ 

    import ovs_bridge 

 

 

class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge): 

    """openvswitch agent br-int specific logic.""" 

 

    def setup_default_table(self): 

        self.install_normal() 

        self.setup_canary_table() 

        self.install_drop(table_id=constants.ARP_SPOOF_TABLE) 

 

    def setup_canary_table(self): 

        self.install_drop(constants.CANARY_TABLE) 

 

    def check_canary_table(self): 

        canary_flows = self.dump_flows(constants.CANARY_TABLE) 

        if canary_flows == '': 

            return constants.OVS_RESTARTED 

        elif canary_flows is None: 

            return constants.OVS_DEAD 

        else: 

            return constants.OVS_NORMAL 

 

    def provision_local_vlan(self, port, lvid, segmentation_id): 

        if segmentation_id is None: 

            dl_vlan = 0xffff 

        else: 

            dl_vlan = segmentation_id 

        self.add_flow(priority=3, 

                      in_port=port, 

                      dl_vlan=dl_vlan, 

                      actions="mod_vlan_vid:%s,normal" % lvid) 

 

    def reclaim_local_vlan(self, port, segmentation_id): 

        if segmentation_id is None: 

            dl_vlan = 0xffff 

        else: 

            dl_vlan = segmentation_id 

        self.delete_flows(in_port=port, dl_vlan=dl_vlan) 

 

    @staticmethod 

    def _dvr_to_src_mac_table_id(network_type): 

        if network_type == p_const.TYPE_VLAN: 

            return constants.DVR_TO_SRC_MAC_VLAN 

        else: 

            return constants.DVR_TO_SRC_MAC 

 

    def install_dvr_to_src_mac(self, network_type, 

                               vlan_tag, gateway_mac, dst_mac, dst_port): 

        table_id = self._dvr_to_src_mac_table_id(network_type) 

        self.add_flow(table=table_id, 

                      priority=4, 

                      dl_vlan=vlan_tag, 

                      dl_dst=dst_mac, 

                      actions="strip_vlan,mod_dl_src:%s," 

                      "output:%s" % (gateway_mac, dst_port)) 

 

    def delete_dvr_to_src_mac(self, network_type, vlan_tag, dst_mac): 

        table_id = self._dvr_to_src_mac_table_id(network_type) 

        self.delete_flows(table=table_id, 

                          dl_vlan=vlan_tag, 

                          dl_dst=dst_mac) 

 

    def add_dvr_mac_vlan(self, mac, port): 

        self.install_goto(table_id=constants.LOCAL_SWITCHING, 

                          priority=4, 

                          in_port=port, 

                          eth_src=mac, 

                          dest_table_id=constants.DVR_TO_SRC_MAC_VLAN) 

 

    def remove_dvr_mac_vlan(self, mac): 

        # REVISIT(yamamoto): match in_port as well? 

        self.delete_flows(table_id=constants.LOCAL_SWITCHING, 

                          eth_src=mac) 

 

    def add_dvr_mac_tun(self, mac, port): 

        # Table LOCAL_SWITCHING will now sort DVR traffic from other 

        # traffic depending on in_port 

        self.install_goto(table_id=constants.LOCAL_SWITCHING, 

                          priority=2, 

                          in_port=port, 

                          eth_src=mac, 

                          dest_table_id=constants.DVR_TO_SRC_MAC) 

 

    def remove_dvr_mac_tun(self, mac, port): 

        self.delete_flows(table_id=constants.LOCAL_SWITCHING, 

                          in_port=port, eth_src=mac) 

 

    def install_arp_spoofing_protection(self, port, ip_addresses): 

        # allow ARPs as long as they match addresses that actually 

        # belong to the port. 

        for ip in ip_addresses: 

            self.install_normal( 

                table_id=constants.ARP_SPOOF_TABLE, priority=2, 

                proto='arp', arp_spa=ip, in_port=port) 

 

        # Now that the rules are ready, direct ARP traffic from the port into 

        # the anti-spoof table. 

        # This strategy fails gracefully because OVS versions that can't match 

        # on ARP headers will just process traffic normally. 

        self.add_flow(table=constants.LOCAL_SWITCHING, 

                      priority=10, proto='arp', in_port=port, 

                      actions=("resubmit(,%s)" % constants.ARP_SPOOF_TABLE)) 

 

    def delete_arp_spoofing_protection(self, port): 

        self.delete_flows(table_id=constants.LOCAL_SWITCHING, 

                          in_port=port, proto='arp') 

        self.delete_flows(table_id=constants.ARP_SPOOF_TABLE, 

                          in_port=port)